Passed
Push — new-api ( 7cf340...18d26d )
by Sebastian
12:35 queued 08:17
created

Label   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 247
Duplicated Lines 0 %

Test Coverage

Coverage 93.5%

Importance

Changes 0
Metric Value
eloc 127
c 0
b 0
f 0
dl 0
loc 247
ccs 115
cts 123
cp 0.935
rs 7.44
wmc 52

9 Methods

Rating   Name   Duplication   Size   Complexity  
B factory() 0 26 6
A setVariable() 0 3 1
B evaluateStringPluralism() 0 23 11
A getForm() 0 3 1
A formatting() 0 13 2
A defaultPlural() 0 14 4
C render() 0 46 16
A __construct() 0 15 1
B getPlural() 0 28 10

How to fix   Complexity   

Complex Class

Complex classes like Label often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Label, and based on these observations, apply Extract Interface, too.

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