Passed
Push — issue-71 ( 957702 )
by Sebastian
06:11
created

Number   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Test Coverage

Coverage 97.65%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 97
c 1
b 0
f 0
dl 0
loc 179
ccs 83
cts 85
cp 0.9765
rs 9.68
wmc 34

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 4
A buildNumberRangeString() 0 10 3
A longOrdinal() 0 7 2
C render() 0 59 15
A toDecimalNumber() 0 13 4
A ordinal() 0 16 6
1
<?php
2
/*
1 ignored issue
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
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
use Seboettg\CiteProc\CiteProc;
12
use Seboettg\CiteProc\Util;
13
use Seboettg\CiteProc\Styles\AffixesTrait;
14
use Seboettg\CiteProc\Styles\DisplayTrait;
15
use Seboettg\CiteProc\Styles\FormattingTrait;
16
use Seboettg\CiteProc\Styles\TextCaseTrait;
17
use SimpleXMLElement;
18
use stdClass;
19
20
21
/**
22
 * Class Number
23
 * @package Seboettg\CiteProc\Rendering
1 ignored issue
show
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
24
 *
25
 * @author Sebastian Böttger <[email protected]>
26
 */
3 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
27
class Number implements Rendering
28
{
29
30
    const RANGE_DELIMITER_HYPHEN = "-";
31
32
    const RANGE_DELIMITER_AMPERSAND = "&";
33
34
    const RANGE_DELIMITER_COMMA = ",";
35
36
    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\Number.
Loading history...
37
        AffixesTrait,
38
        TextCaseTrait,
39
        DisplayTrait;
40
41
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
42
     * @var string
43
     */
44
    private $variable;
0 ignored issues
show
Coding Style introduced by
Private member variable "variable" must be prefixed with an underscore
Loading history...
45
46
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
47
     * @var string
48
     */
49
    private $form;
0 ignored issues
show
Coding Style introduced by
Private member variable "form" must be prefixed with an underscore
Loading history...
50
51 47
    public function __construct(SimpleXMLElement $node)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
52
    {
53
        //<number variable="edition" form="ordinal"/>
54
        /** @var SimpleXMLElement $attribute */
3 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
55 47
        foreach ($node->attributes() as $attribute) {
56 47
            switch ($attribute->getName()) {
57 47
                case 'variable':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
58 47
                    $this->variable = (string) $attribute;
59 47
                    break;
60 45
                case 'form':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
61 47
                    $this->form = (string) $attribute;
62
            }
63
        }
64
65 47
        $this->initFormattingAttributes($node);
66 47
        $this->initAffixesAttributes($node);
67 47
        $this->initTextCaseAttributes($node);
68 47
    }
69
70
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
71
     * @param stdClass $data
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
72
     * @param int|null $citationNumber
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
73
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
74
     */
75 26
    public function render($data, $citationNumber = null)
76
    {
77 26
        $lang = (isset($data->language) && $data->language != 'en') ? $data->language : 'en';
78
79 26
        if (empty($this->variable) || empty($data->{$this->variable})) {
80 8
            return "";
81
        }
82 20
        $number = $data->{$this->variable};
83 20
        $decimalNumber = $this->toDecimalNumber($number);
84 20
        switch ($this->form) {
85 20
            case 'ordinal':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
86 4
                if (preg_match("/\s*(\d+)\s*([\-\-&,])\s*(\d+)\s*/", $decimalNumber, $matches)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
87 2
                    $num1 = self::ordinal($matches[1]);
88 2
                    $num2 = self::ordinal($matches[3]);
89 2
                    $text = $this->buildNumberRangeString($num1, $num2, $matches[2]);
90
                } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
91 2
                    $text = self::ordinal($decimalNumber);
92
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
93 4
                break;
94 17
            case 'long-ordinal':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
95 3
                if (preg_match("/\s*(\d+)\s*([\-\-&,])\s*(\d+)\s*/", $decimalNumber, $matches)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
96 2
                    if ($this->textCase === "capitalize-first" || $this->textCase === "sentence") {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
97 1
                        $num1 = self::longOrdinal($matches[1]);
98 1
                        $num2 = self::longOrdinal($matches[3]);
99
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
100 2
                        $num1 = $this->applyTextCase(self::longOrdinal($matches[1]));
101 2
                        $num2 = $this->applyTextCase(self::longOrdinal($matches[3]));
102
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
103 2
                    $text = $this->buildNumberRangeString($num1, $num2, $matches[2]);
104
                } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
105 1
                    $text = self::longOrdinal($decimalNumber);
106
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
107 3
                break;
108 15
            case 'roman':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
109 4
                if (preg_match("/\s*(\d+)\s*([\-\-&,])\s*(\d+)\s*/", $decimalNumber, $matches)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
110 1
                    $num1 = Util\NumberHelper::dec2roman($matches[1]);
111 1
                    $num2 = Util\NumberHelper::dec2roman($matches[3]);
112 1
                    $text = $this->buildNumberRangeString($num1, $num2, $matches[2]);
113
                } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
114 3
                    $text = Util\NumberHelper::dec2roman($decimalNumber);
115
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
116 4
                break;
117 12
            case 'numeric':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
118
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
119
                /*
120
                 During the extraction, numbers separated by a hyphen are stripped of intervening spaces (“2 - 4”
121
                 becomes “2-4”). Numbers separated by a comma receive one space after the comma (“2,3” and “2 , 3”
122
                 become “2, 3”), while numbers separated by an ampersand receive one space before and one after the
123
                 ampersand (“2&3” becomes “2 & 3”).
124
                 */
125 12
                $decimalNumber = $data->{$this->variable};
126 12
                if (preg_match("/\s*(\d+)\s*([\-\-&,])\s*(\d+)\s*/", $decimalNumber, $matches)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
127 9
                    $text = $this->buildNumberRangeString($matches[1], $matches[3], $matches[2]);
128
                } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
129 3
                    $text = $decimalNumber;
130
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
131 12
                break;
132
        }
133 20
        return $this->wrapDisplayBlock($this->addAffixes($this->format($this->applyTextCase($text, $lang))));
134
    }
135
136
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
137
     * @param $num
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
138
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
139
     */
140 4
    public static function ordinal($num) {
0 ignored issues
show
Coding Style introduced by
Opening brace should be on a new line
Loading history...
141 4
        if (($num / 10) % 10 == 1) {
142 1
            $ordinalSuffix = CiteProc::getContext()->getLocale()->filter('terms', 'ordinal')->single;
143 4
        } elseif ($num % 10 == 1) {
144
            $ordinalSuffix = CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-01')->single;
145 4
        } elseif ($num % 10 == 2) {
146 2
            $ordinalSuffix = CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-02')->single;
147 4
        } elseif ($num % 10 == 3) {
148 1
            $ordinalSuffix = CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-03')->single;
149
        } else {
150 3
            $ordinalSuffix = CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-04')->single;
151
        }
152 4
        if (empty($ordinalSuffix)) {
153 3
            $ordinalSuffix = CiteProc::getContext()->getLocale()->filter('terms', 'ordinal')->single;
154
        }
155 4
        return $num . $ordinalSuffix;
156
    }
157
158
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
159
     * @param $num
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
160
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
161
     */
162 3
    public static function longOrdinal($num) {
0 ignored issues
show
Coding Style introduced by
Opening brace should be on a new line
Loading history...
163 3
        $num = sprintf("%02d", $num);
164 3
        $ret = CiteProc::getContext()->getLocale()->filter('terms', 'long-ordinal-' . $num)->single;
165 3
        if (!$ret) {
166
            return self::ordinal($num);
167
        }
168 3
        return $ret;
169
    }
170
171
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
172
     * @param string|int $num1
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
173
     * @param string|int $num2
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
174
     * @param string $delim
3 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
175
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
176
     */
177 11
    public function buildNumberRangeString($num1, $num2, $delim) {
0 ignored issues
show
Coding Style introduced by
Opening brace should be on a new line
Loading history...
178
179 11
        if (self::RANGE_DELIMITER_AMPERSAND === $delim) {
180 1
            $numRange = "$num1 " . htmlentities(self::RANGE_DELIMITER_AMPERSAND) . " $num2";
181 11
        } else if (self::RANGE_DELIMITER_COMMA === $delim) {
182 1
            $numRange = $num1 . htmlentities(self::RANGE_DELIMITER_COMMA) . " $num2";
183
        } else {
184 11
            $numRange = $num1 . self::RANGE_DELIMITER_HYPHEN . $num2;
185
        }
186 11
        return $numRange;
187
    }
188
189
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
190
     * @param string $number
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
191
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
192
     */
193 20
    private function toDecimalNumber($number)
1 ignored issue
show
Coding Style introduced by
Private method name "Number::toDecimalNumber" must be prefixed with an underscore
Loading history...
194
    {
195 20
        $decimalNumber = $number;
196 20
        if (Util\NumberHelper::isRomanNumber($number) || Util\NumberHelper::isRomanRange($number)) {
197 2
            if (preg_match("/\s*([^\-\-&,]+)\s*([\-\-&,])\s*([^\-\-&,]+)\s*/", $number, $matches)) {
198 1
                $num1 = Util\NumberHelper::roman2Dec($matches[1]);
199 1
                $num2 = Util\NumberHelper::roman2Dec($matches[3]);
200 1
                $decimalNumber = $num1 . $matches[2] . $num2;
201
            } else {
202 1
                $decimalNumber = Util\NumberHelper::roman2Dec($number);
203
            }
204
        }
205 20
        return $decimalNumber;
206
    }
207
}
208