Passed
Push — new-api ( 42b595...e6ef7d )
by Sebastian
05:57
created

Label::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 7
c 0
b 0
f 0
nc 1
nop 7
dl 0
loc 16
ccs 8
cts 8
cp 1
crap 1
rs 10
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