Test Failed
Pull Request — master (#110)
by Sebastian
05:14
created

Text::render()   D

Complexity

Conditions 16
Paths 176

Size

Total Lines 43
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 16

Importance

Changes 0
Metric Value
cc 16
eloc 34
nc 176
nop 2
dl 0
loc 43
ccs 33
cts 33
cp 1
crap 16
rs 4.9333
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 118
                $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)
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...
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
                if (!CiteProcHelper::isUsingAffixesByMarkupExtentsion($data, $this->toRenderTypeValue)) {
116 83
					$renderedText = $this->applyAdditionalMarkupFunction($data, $renderedText);
117 69
				}
118 62
                break;
119 62
            case 'macro':
120 26
                $renderedText = $this->renderMacro($data);
121 26
                break;
122 26
            case 'term':
123 26
                $term = CiteProc::getContext()
124 26
                    ->getLocale()
125 26
                    ->filter("terms", $this->toRenderTypeValue, $this->form)
126
                    ->single;
127 102
                $renderedText = !empty($term) ? $this->applyTextCase($term, $lang) : "";
128 102
        }
129
        if (!empty($renderedText)) {
130 102
            $renderedText = $this->formatRenderedText($data, $renderedText);
131
        }
132
        return $renderedText;
133
    }
134
135
    /**
136 66
     * @return string
137
     */
138 66
    public function getSource()
139
    {
140
        return $this->toRenderType;
141
    }
142
143
    /**
144 66
     * @return string
145
     */
146 66
    public function getVariable()
147
    {
148
        return $this->toRenderTypeValue;
149 23
    }
150
151 23
    private function renderPage($page)
152 21
    {
153 21
        if (preg_match(NumberHelper::PATTERN_COMMA_AMPERSAND_RANGE, $page)) {
154 21
            $page = $this->normalizeDateRange($page);
155 20
            $ranges = preg_split("/[-–]/", trim($page));
156 20
            if (count($ranges) > 1) {
157
                if (!empty(CiteProc::getContext()->getGlobalOptions())
158 9
                    && !empty(CiteProc::getContext()->getGlobalOptions()->getPageRangeFormat())
159 9
                ) {
160 9
                    return PageHelper::processPageRangeFormats(
161
                        $ranges,
162
                        CiteProc::getContext()->getGlobalOptions()->getPageRangeFormat()
163 11
                    );
164 11
                }
165
                list($from, $to) = $ranges;
166
                return $from . "–" . $to;
167 4
            }
168
        }
169
        return $page;
170 8
    }
171
172 8
    private function renderLocator($data, $citationNumber)
173 8
    {
174 4
        $citationItem = CiteProc::getContext()->getCitationItemById($data->id);
175 4
        if (!empty($citationItem->label)) {
176 4
            $locatorData = new stdClass();
177 4
            $propertyName = Locator::mapLocatorLabelToRenderVariable($citationItem->label);
178 4
            $locatorData->{$propertyName} = trim($citationItem->locator);
179 4
            $renderTypeValueTemp = $this->toRenderTypeValue;
180 4
            $this->toRenderTypeValue = $propertyName;
181 4
            $result = $this->render($locatorData, $citationNumber);
182
            $this->toRenderTypeValue = $renderTypeValueTemp;
183 4
            return $result;
184
        }
185
        return isset($citationItem->locator) ? trim($citationItem->locator) : '';
186 21
    }
187
188 21
    private function normalizeDateRange($page)
189 20
    {
190
        if (preg_match("/^(\d+)\s?--?\s?(\d+)$/", trim($page), $matches)) {
191 1
            return $matches[1]."-".$matches[2];
192
        }
193
        return $page;
194
    }
195
196
    /**
197
     * @param  $data
198
     * @param  $renderedText
199 85
     * @return mixed
200
     */
201 85
    private function applyAdditionalMarkupFunction($data, $renderedText)
202
    {
203
        return CiteProcHelper::applyAdditionMarkupFunction($data, $this->toRenderTypeValue, $renderedText);
204
    }
205
206
    /**
207
     * @param  $data
208
     * @param  $lang
209 77
     * @return string
210
     */
211
    private function renderVariable($data, $lang)
212
    {
213 77
        // check if there is an attribute with prefix short or long e.g. shortTitle or longAbstract
214 77
        // test case group_ShortOutputOnly.json
215 77
        $value = "";
216 77
        if (in_array($this->form, ["short", "long"])) {
217 77
            $attrWithPrefix = $this->form . ucfirst($this->toRenderTypeValue);
218 1
            $attrWithSuffix = $this->toRenderTypeValue . "-" . $this->form;
219
            if (isset($data->{$attrWithPrefix}) && !empty($data->{$attrWithPrefix})) {
220 76
                $value = $data->{$attrWithPrefix};
221 3
            } else {
222
                if (isset($data->{$attrWithSuffix}) && !empty($data->{$attrWithSuffix})) {
223 76
                    $value = $data->{$attrWithSuffix};
224 77
                } else {
225
                    if (isset($data->{$this->toRenderTypeValue})) {
226
                        $value = $data->{$this->toRenderTypeValue};
227
                    }
228
                }
229
            }
230
        } else {
231
            if (!empty($data->{$this->toRenderTypeValue})) {
232
                $value = $data->{$this->toRenderTypeValue};
233 77
            }
234 77
        }
235 77
        return $this->applyTextCase(
236
            StringHelper::clearApostrophes(
237 77
                htmlspecialchars($value, ENT_HTML5)
238
            ),
239
            $lang
240
        );
241
    }
242
243
    /**
244
	 * @param  $data
245 102
	 * @param  $renderedText
246
     * @return string
247 102
     */
248 102
    private function formatRenderedText($data, $renderedText)
249 102
    {
250 102
        $text = $this->format($renderedText);
251
        $res = $this->addAffixes($text);
252 102
		if (CiteProcHelper::isUsingAffixesByMarkupExtentsion($data, $this->toRenderTypeValue)) {
253 102
			$res = $this->applyAdditionalMarkupFunction($data, $res);
254
		}
255
        if (!empty($res)) {
256
            $res = $this->removeConsecutiveChars($res);
257
        }
258
        $res = $this->addSurroundingQuotes($res);
259
        return $this->wrapDisplayBlock($res);
260
    }
261 15
262
    /**
263 15
     * @param  $data
264 15
     * @param  $citationNumber
265 15
     * @return int|mixed
266
     */
267
    private function renderCitationNumber($data, $citationNumber)
268
    {
269
        $renderedText = $citationNumber + 1;
270
        $renderedText = $this->applyAdditionalMarkupFunction($data, $renderedText);
271
        return $renderedText;
272 62
    }
273
274 62
    /**
275 62
     * @param  $data
276
     * @return string
277 1
     */
278 1
    private function renderMacro($data)
279 1
    {
280
        $macro = CiteProc::getContext()->getMacro($this->toRenderTypeValue);
281
        if (is_null($macro)) {
282 62
            try {
283
                throw new CiteProcException("Macro \"".$this->toRenderTypeValue."\" does not exist.");
284 62
            } catch (CiteProcException $e) {
285
                $renderedText = "";
286
            }
287
        } else {
288
            $renderedText = $macro->render($data);
289
        }
290
        return $renderedText;
291
    }
292
}
293