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

Label::getPlural()   B

Complexity

Conditions 10
Paths 12

Size

Total Lines 28
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 10.1167

Importance

Changes 0
Metric Value
cc 10
eloc 21
c 0
b 0
f 0
nc 12
nop 3
dl 0
loc 28
ccs 17
cts 19
cp 0.8947
crap 10.1167
rs 7.6666

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
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\Rendering\Label;
12
13
use Seboettg\CiteProc\CiteProc;
14
use Seboettg\CiteProc\Locale\Locale;
15
use Seboettg\CiteProc\Locale\TermForm;
16
use Seboettg\CiteProc\Rendering\Observer\RenderingObserver;
17
use Seboettg\CiteProc\Rendering\Observer\RenderingObserverTrait;
18
use Seboettg\CiteProc\Rendering\Rendering;
19
use Seboettg\CiteProc\Styles\StylesRenderer;
20
use SimpleXMLElement;
21
use function Seboettg\CiteProc\getCurrentById;
22
23
/**
24
 * Class Label
25
 * @package Seboettg\CiteProc\Rendering
26
 *
27
 * @author Sebastian Böttger <[email protected]>
28
 */
29
class Label implements Rendering, RenderingObserver
30
{
31
    use RenderingObserverTrait;
32
33
    private $variable;
34
35
    private $stripPeriods;
36
37
    /** @var TermForm  */
38
    private $form;
39
40
    /** @var Plural */
41
    private $plural;
42
43
    /** @var Locale */
44
    private $locale;
45
46
    /** @var StylesRenderer */
47
    private $stylesRenderer;
48
49 63
    public static function factory(SimpleXMLElement $node): Label
50
    {
51 63
        $variable = $form = $plural = null;
52 63
        $stripPeriods = false;
53 63
        $context = CiteProc::getContext();
54
55 63
        foreach ($node->attributes() as $attribute) {
56 62
            switch ($attribute->getName()) {
57 62
                case "variable":
58 47
                    $variable = (string) $attribute;
59 47
                    break;
60 59
                case "form":
61 57
                    $form = new TermForm((string) $attribute);
62 57
                    break;
63 57
                case "plural":
64 5
                    $plural = new Plural((string) $attribute);
65 5
                    break;
66 57
                case "strip-periods":
67 62
                    $stripPeriods = (bool) $attribute;
68
            }
69
        }
70 63
        $locale = $context->getLocale();
71 63
        $stylesRenderer = StylesRenderer::factory($node);
72 63
        $label = new Label($variable, $form, $plural, $stylesRenderer, $locale, $stripPeriods);
73 63
        $context->addObserver($label);
74 63
        return $label;
75
    }
76
77
78
    /**
79
     * Label constructor.
80
     * @param string|null $variable
81
     * @param TermForm|null $form
82
     * @param Plural|null $plural
83
     * @param StylesRenderer $stylesRenderer
84
     * @param Locale $locale
85
     * @param bool $stripPeriods
86
     */
87 63
    public function __construct(
88
        ?string $variable,
89
        ?TermForm $form,
90
        ?Plural $plural,
91
        StylesRenderer $stylesRenderer,
92
        Locale $locale,
93
        bool $stripPeriods
94
    ) {
95 63
        $this->variable = $variable;
96 63
        $this->form = $form;
97 63
        $this->plural = $plural;
98 63
        $this->stylesRenderer = $stylesRenderer;
99 63
        $this->locale = $locale;
100 63
        $this->stripPeriods = $stripPeriods;
101 63
        $this->initObserver();
102 63
    }
103
104
    /**
105
     * @param $data
106
     * @param int|null $citationNumber
107
     * @return string
108
     */
109 46
    public function render($data, $citationNumber = null): string
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...
110
    {
111 46
        $lang = (isset($data->language) && $data->language != 'en') ? $data->language : 'en';
112 46
        $this->stylesRenderer->getTextCase()->setLanguage($lang);
113 46
        $text = '';
114 46
        $variables = null !== $this->variable ? explode(' ', $this->variable) : [];
115 46
        $form = !empty($this->form) ? $this->form : 'long';
116 46
        $plural = $this->defaultPlural();
117
118 46
        if ($this->variable === "editortranslator") {
119 1
            if (isset($data->editor) && isset($data->translator)) {
120 1
                $plural = $this->getPlural($data, $plural, "editortranslator");
121 1
                $term = $this->locale->filter('terms', "editortranslator", (string)$form);
122 1
                $pluralForm = $term->{$plural};
123 1
                if (!empty($pluralForm)) {
124 1
                    $text = $pluralForm;
125
                }
126
            }
127 45
        } elseif ($this->variable === "locator") {
128 7
            $id = $data->id;
129 7
            $citationItem = getCurrentById($this->citationItems, $id);
130 7
            if (!empty($citationItem->label)) {
131 4
                $plural = $this->evaluateStringPluralism($citationItem->locator, $citationItem->label);
132 4
                $term = $this->locale->filter('terms', $citationItem->label, (string)$form);
133 4
                $pluralForm = $term->{$plural} ?? "";
134 4
                if (!empty($citationItem->locator) && !empty($pluralForm)) {
135 7
                    $text = $pluralForm;
136
                }
137
            }
138
        } else {
139 40
            foreach ($variables as $variable) {
140 40
                if (isset($data->{$variable})) {
141 37
                    $plural = $this->getPlural($data, $plural, $variable);
142 37
                    $term = $this->locale->filter('terms', $variable, (string)$form);
143 37
                    $pluralForm = $term->{$plural} ?? "";
144 37
                    if (!empty($data->{$variable}) && !empty($pluralForm)) {
145 13
                        $text = $pluralForm;
146 40
                        break;
147
                    }
148
                }
149
            }
150
        }
151
152 46
        return $this->formatting($text);
153
    }
154
155
    /**
156
     * @param string $str
157
     * @param string $variable
158
     * @return string
159
     */
160 13
    private function evaluateStringPluralism(string $str, string $variable): string
161
    {
162 13
        $plural = 'single';
163 13
        if (!empty($str)) {
164
            switch ($variable) {
165 12
                case 'page':
166 4
                case 'chapter':
167 2
                case 'folio':
168 11
                    $pageRegex = "/([a-zA-Z]*)([0-9]+)\s*(?:–|-)\s*([a-zA-Z]*)([0-9]+)/";
169 11
                    $err = preg_match($pageRegex, $str, $matches);
170 11
                    if ($err !== false && count($matches) == 0) {
171 3
                        $plural = 'single';
172 9
                    } elseif ($err !== false && count($matches)) {
173 9
                        $plural = 'multiple';
174
                    }
175 11
                    break;
176
                default:
177 1
                    if (is_numeric($str)) {
178
                        return $str > 1 ? 'multiple' : 'single';
179
                    }
180
            }
181
        }
182 13
        return $plural;
183
    }
184
185
    /**
186
     * @param string $variable
187
     */
188 33
    public function setVariable(string $variable)
189
    {
190 33
        $this->variable = $variable;
191 33
    }
192
193
    /**
194
     * @param $data
195
     * @param $plural
196
     * @param $variable
197
     * @return string
198
     */
199 38
    protected function getPlural($data, $plural, $variable): string
200
    {
201
202 38
        if ($variable === "editortranslator" && isset($data->editor)) {
203 1
            $var = $data->editor;
204
        } else {
205 37
            $var = $data->{$variable};
206
        }
207 38
        if (((!isset($this->plural) || empty($plural))) && !empty($var)) {
208 37
            if (is_array($var)) {
209 33
                $count = count($var);
210 33
                if ($count == 1) {
211 25
                    $plural = 'single';
212 25
                    return $plural;
213 12
                } elseif ($count > 1) {
214 12
                    $plural = 'multiple';
215 12
                    return $plural;
216
                }
217
                return $plural;
218
            } else {
219 8
                return $this->evaluateStringPluralism($data->{$variable}, $variable);
220
            }
221
        } else {
222 1
            if ($this->plural != "always") {
0 ignored issues
show
introduced by
The condition $this->plural != 'always' is always true.
Loading history...
223 1
                $plural = $this->evaluateStringPluralism($data->{$variable}, $variable);
224 1
                return $plural;
225
            }
226
            return $plural;
227
        }
228
    }
229
230
    /**
231
     * @return string
232
     */
233 32
    public function getForm()
234
    {
235 32
        return $this->form;
236
    }
237
238
    /**
239
     * @param $text
240
     * @return string
241
     */
242 46
    protected function formatting(?string $text): string
243
    {
244 46
        if (empty($text)) {
245 35
            return "";
246
        }
247
        //if ($this->stripPeriods) {
248
        //    $text = str_replace('.', '', $text);
249
        //}
250
251 18
        $text = preg_replace("/\s&\s/", " &#38; ", $text); //replace ampersands by html entity
252 18
        $text = $this->stylesRenderer->renderTextCase($text);
253 18
        $text = $this->stylesRenderer->renderFormatting($text);
254 18
        return $this->stylesRenderer->renderAffixes($text);
255
    }
256
257
    /**
258
     * @return string
259
     */
260 46
    protected function defaultPlural(): string
261
    {
262 46
        $plural = "";
263 46
        switch ($this->plural) {
264 46
            case 'never':
265
                $plural = 'single';
266
                break;
267 46
            case 'always':
268
                $plural = 'multiple';
269
                break;
270 46
            case 'contextual':
271
            default:
272
        }
273 46
        return $plural;
274
    }
275
}
276