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

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
259
    }
260
261
    /**
262
     * @param $text
263
     * @param $lang
264
     * @return string
265
     */
266 45
    protected function formatting($text)
267
    {
268 45
        if (empty($text)) {
269 34
            return "";
270
        }
271 18
        if ($this->stripPeriods) {
272
            $text = str_replace('.', '', $text);
273
        }
274
275 18
        $text = preg_replace("/\s&\s/", " &#38; ", $text); //replace ampersands by html entity
276 18
        $text = $this->textCase->render($text);
277 18
        $text = $this->formatting->render($text);
278 18
        return $this->affixes->render($text);
279
    }
280
281
    /**
282
     * @return string
283
     */
284 45
    protected function defaultPlural()
285
    {
286 45
        $plural = "";
287 45
        switch ($this->plural) {
288 45
            case 'never':
289
                $plural = 'single';
290
                break;
291 45
            case 'always':
292
                $plural = 'multiple';
293
                break;
294 45
            case 'contextual':
295
            default:
296
        }
297 45
        return $plural;
298
    }
299
}
300