Passed
Push — master ( 9db44e...ff01a4 )
by Sebastian
03:38 queued 10s
created

Number::toDecimalNumber()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

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