Test Failed
Push — master ( 9d4e41...1cd52c )
by Sebastian
03:24
created

Number::buildNumberRangeString()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 3
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
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
18
19
/**
20
 * Class Number
21
 * @package Seboettg\CiteProc\Rendering
22
 *
23
 * @author Sebastian Böttger <[email protected]>
24
 */
25
class Number implements RenderingInterface
26
{
27
28
    const RANGE_DELIMITER_HYPHEN = "-";
29
30
    const RANGE_DELIMITER_AMPERSAND = "&";
31
32
    const RANGE_DELIMITER_COMMA = ",";
33
34
    use FormattingTrait,
35
        AffixesTrait,
36
        TextCaseTrait,
37
        DisplayTrait;
38
39
    private $variable;
40
41
    private $form;
42
43
    public function __construct(\SimpleXMLElement $node)
44
    {
45
        //<number variable="edition" form="ordinal"/>
46
        /** @var \SimpleXMLElement $attribute */
47 View Code Duplication
        foreach ($node->attributes() as $attribute) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
48
            switch ($attribute->getName()) {
49
                case 'variable':
50
                    $this->variable = (string) $attribute;
51
                    break;
52
                case 'form':
53
                    $this->form = (string) $attribute;
54
            }
55
        }
56
57
        $this->initFormattingAttributes($node);
58
        $this->initAffixesAttributes($node);
59
        $this->initTextCaseAttributes($node);
60
    }
61
62
    /**
63
     * @param \stdClass $data
64
     * @param int|null $citationNumber
65
     * @return string
66
     */
67
    public function render($data, $citationNumber = null)
68
    {
69
        $lang = (isset($data->language) && $data->language != 'en') ? $data->language : 'en';
70
71
        if (empty($this->variable) || empty($data->{$this->variable})) {
72
            return "";
73
        }
74
        switch ($this->form) {
75 View Code Duplication
            case 'ordinal':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
76
                $var = $data->{$this->variable};
77
                if (preg_match("/\s*(\d+)\s*[\-\-\&,]\s*(\d+)\s*/", $var, $matches)) {
78
                    $num1 = self::ordinal($matches[1]);
79
                    $num2 = self::ordinal($matches[3]);
80
                    $text = $this->buildNumberRangeString($num1, $num2, $matches[2]);
81
                } else {
82
                    $text = self::ordinal($var);
83
                }
84
                break;
85 View Code Duplication
            case 'long-ordinal':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
                $var = $data->{$this->variable};
87
                if (preg_match("/\s*(\d+)\s*[\-\-\&,]\s*(\d+)\s*/", $var, $matches)) {
88
                    $num1 = self::longOrdinal($matches[1]);
89
                    $num2 = self::longOrdinal($matches[3]);
90
                    $text = $this->buildNumberRangeString($num1, $num2, $matches[2]);
91
                } else {
92
                    $text = self::longOrdinal($var);
93
                }
94
                break;
95 View Code Duplication
            case 'roman':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
                $var = $data->{$this->variable};
97
                if (preg_match("/\s*(\d+)\s*[\-\-\&,]\s*(\d+)\s*/", $var, $matches)) {
98
                    $num1 = Util\Number::dec2roman($matches[1]);
99
                    $num2 = Util\Number::dec2roman($matches[3]);
100
                    $text = $this->buildNumberRangeString($num1, $num2, $matches[2]);
101
                } else {
102
                    $text =  Util\Number::dec2roman($var);
103
                }
104
                break;
105
            case 'numeric':
106
            default:
107
                /*
108
                 During the extraction, numbers separated by a hyphen are stripped of intervening spaces (“2 - 4”
109
                 becomes “2-4”). Numbers separated by a comma receive one space after the comma (“2,3” and “2 , 3”
110
                 become “2, 3”), while numbers separated by an ampersand receive one space before and one after the
111
                 ampersand (“2&3” becomes “2 & 3”).
112
                 */
113
                $var = $data->{$this->variable};
114
                if (preg_match("/\s*(\d+)\s*[\-\-\&,]\s*(\d+)\s*/", $var, $matches)) {
115
                    $text = $this->buildNumberRangeString($matches[1], $matches[3], $matches[2]);
116
                } else {
117
                    $text =  Util\Number::dec2roman($var);
118
                }
119
                break;
120
        }
121
        return $this->wrapDisplayBlock($this->addAffixes($this->format($this->applyTextCase($text, $lang))));
122
    }
123
124
    public static function ordinal($num) {
125
        if (($num / 10) % 10 == 1) {
126
            $num .= CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-04')->single;
127
        } elseif ($num % 10 == 1) {
128
            $num .= CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-01')->single;
129
        } elseif ($num % 10 == 2) {
130
            $num .= CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-02')->single;
131
        } elseif ($num % 10 == 3) {
132
            $num .= CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-03')->single;
133
        } else {
134
            $num .= CiteProc::getContext()->getLocale()->filter('terms', 'ordinal-04')->single;
135
        }
136
        return $num;
137
    }
138
139
140
    public static function longOrdinal($num) {
141
        $num = sprintf("%02d", $num);
142
        $ret = CiteProc::getContext()->getLocale()->filter('terms', 'long-ordinal-' . $num)->single;
143
        if (!$ret) {
144
            return self::ordinal($num);
145
        }
146
        return $ret;
147
    }
148
149
    /**
150
     * @param string|int $num1
151
     * @param string|int $num2
152
     * @param string $delim
153
     * @return string
154
     */
155
    public function buildNumberRangeString($num1, $num2, $delim) {
156
157
        if (self::RANGE_DELIMITER_AMPERSAND === $delim) {
158
            $numRange = "$num1 " . self::RANGE_DELIMITER_AMPERSAND . " $num2";
159
        } else if (self::RANGE_DELIMITER_COMMA === $delim) {
160
            $numRange = $num1 . htmlentities(self::RANGE_DELIMITER_COMMA) . " $num2";
161
        } else  {
162
            $numRange = $num1 . self::RANGE_DELIMITER_HYPHEN . $num2;
163
        }
164
        return $numRange;
165
    }
166
167
168
169
}