Passed
Push — new-api ( 15a925...220eb6 )
by Sebastian
11:23
created

DatePart::factory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 0
loc 10
ccs 9
cts 9
cp 1
crap 2
rs 10
c 0
b 0
f 0
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\Date;
11
12
use Seboettg\CiteProc\CiteProc;
13
use Seboettg\CiteProc\Locale\Locale;
14
use Seboettg\CiteProc\Rendering\HasParent;
15
use Seboettg\CiteProc\Rendering\Layout;
16
use Seboettg\CiteProc\Rendering\Number\Number;
17
use Seboettg\CiteProc\Styles\StylesRenderer;
18
use SimpleXMLElement;
19
20
/**
21
 * Class DatePart
22
 * @package Seboettg\CiteProc\Rendering\Date
23
 *
24
 * @author Sebastian Böttger <[email protected]>
25
 */
26
class DatePart implements HasParent
27
{
28
29
    const DEFAULT_RANGE_DELIMITER = "–";
30
31
    /** @var string|null */
32
    private $name;
33
34
    /** @var string|null */
35
    private $form;
36
37
    /** @var string|null */
38
    private $rangeDelimiter;
39
40
    /** @var Date */
41
    private $parent;
42
43
    /** @var StylesRenderer */
44
    private $stylesRenderer;
45
46
    /** @var Number */
47
    private $number;
48
49
    /** @var Locale */
50
    private $locale;
51
52 72
    public static function factory(SimpleXMLElement $node): DatePart
53
    {
54 72
        $name = (string) $node->attributes()['name'];
55 72
        $form = (string) $node->attributes()['form'];
56 72
        $rangeDelimiter = (string) $node->attributes()['range-delimiter'];
57 72
        $rangeDelimiter = empty($rangeDelimiter) ? self::DEFAULT_RANGE_DELIMITER : $rangeDelimiter;
58 72
        $stylesRenderer = StylesRenderer::factory($node);
59 72
        $locale = CiteProc::getContext()->getLocale();
60 72
        $number = new Number(null, null, $locale, $stylesRenderer);
61 72
        return new self($name, $form, $rangeDelimiter, $stylesRenderer, $number, $locale);
62
    }
63
64 72
    public function __construct(
65
        ?string $name,
66
        ?string $form,
67
        ?string $rangeDelimiter,
68
        StylesRenderer $stylesRenderer,
69
        Number $number,
70
        Locale $locale
71
    ) {
72 72
        $this->name = $name;
73 72
        $this->form = $form;
74 72
        $this->rangeDelimiter = $rangeDelimiter;
75 72
        $this->stylesRenderer = $stylesRenderer;
76 72
        $this->number = $number;
77 72
        $this->locale = $locale;
78 72
    }
79
80
    /**
81
     * @param DateTime $date
82
     * @param Date $parent
83
     * @return string
84
     */
85 62
    public function render(DateTime $date, Date $parent): string
86
    {
87 62
        $this->parent = $parent; //set parent
88 62
        $text = $this->renderWithoutAffixes($date);
89 62
        return !empty($text) ? $this->stylesRenderer->renderAffixes($text) : "";
90
    }
91
92
    /**
93
     * @param DateTime $date
94
     * @param Date|null $parent
95
     * @return string
96
     */
97 62
    public function renderWithoutAffixes(DateTime $date, Date $parent = null): string
98
    {
99 62
        if (!is_null($parent)) {
100 1
            $this->parent = $parent;
101
        }
102 62
        $text = "";
103 62
        switch ($this->name) {
104 62
            case 'year':
105 61
                $text = $this->renderYear($date);
106 61
                break;
107 19
            case 'month':
108 19
                $text = $this->renderMonth($date);
109 19
                break;
110 15
            case 'day':
111 15
                $text = $this->renderDay($date);
112
        }
113
114 62
        return !empty($text) ? $this->stylesRenderer->renderFormatting(
115 61
            $this->stylesRenderer->renderTextCase($text)
116 62
        ) : "";
117
    }
118
119
    /**
120
     * @return string
121
     */
122
    public function getForm()
123
    {
124
        return $this->form;
125
    }
126
127
    /**
128
     * @return string
129
     */
130 51
    public function getName()
131
    {
132 51
        return $this->name;
133
    }
134
135
    /**
136
     * @return string
137
     */
138 1
    public function getRangeDelimiter()
139
    {
140 1
        return $this->rangeDelimiter;
141
    }
142
143
    /**
144
     * @param DateTime $date
145
     * @return string|int
146
     */
147 61
    protected function renderYear(DateTime $date)
148
    {
149 61
        $text = $date->getYear();
150 61
        if ($text > 0 && $text < 1000) {
151
            $text = $text . $this->locale->filter("terms", "ad")->single;
152
            return $text;
153 61
        } elseif ($text < 0) {
154
            $text = $text * -1;
155
            $text = $text . $this->locale->filter("terms", "bc")->single;
156
            return $text;
157
        }
158 61
        return $text;
159
    }
160
161
    /**
162
     * @param DateTime $date
163
     * @return string
164
     */
165 19
    protected function renderMonth(DateTime $date)
166
    {
167 19
        if ($date->getMonth() < 1 || $date->getMonth() > 12) {
168 2
            return "";
169
        }
170
171 17
        $text = $date->getMonth();
172
173 17
        $form = !empty($this->form) ? $this->form : "long";
174
        switch ($form) {
175 17
            case 'numeric':
176 1
                break;
177 17
            case 'numeric-leading-zeros':
178 3
                $text = sprintf("%02d", $text);
179 3
                break;
180 15
            case 'short':
181 11
            case 'long':
182
            default:
183 15
                $text = $this->monthFromLocale($text, $form);
184 15
                break;
185
        }
186 17
        return $text;
187
    }
188
189
    /**
190
     * @param DateTime $date
191
     * @return int|string
192
     */
193 15
    protected function renderDay(DateTime $date)
194
    {
195 15
        if ($date->getDay() < 1 || $date->getDay() > 31) {
196 2
            return "";
197
        }
198
199 15
        $text = $date->getDay();
200 15
        $form = !empty($this->form) ? $this->form : $this->parent->getForm();
201
        switch ($form) {
202 15
            case 'numeric':
203 1
                break;
204 15
            case 'numeric-leading-zeros':
205 3
                $text = sprintf("%02d", $text);
206 3
                break;
207 13
            case 'ordinal':
208
                $limitDayOrdinals =
209
                    CiteProc::getContext()->getLocale()->filter("options", "limit-day-ordinals-to-day-1");
210
                if (!$limitDayOrdinals || Layout::getNumberOfCitedItems() <= 1) {
0 ignored issues
show
introduced by
$limitDayOrdinals is of type stdClass, thus it always evaluated to true.
Loading history...
211
                    $text = $this->number->ordinal($text);
212
                }
213
        }
214 15
        return $text;
215
    }
216
217
    /**
218
     * @param $text
219
     * @param $form
220
     * @return mixed
221
     */
222 15
    protected function monthFromLocale($text, $form)
223
    {
224 15
        if (empty($form)) {
225
            $form = "long";
226
        }
227 15
        $month = 'month-' . sprintf('%02d', $text);
228 15
        $text = $this->locale->filter('terms', $month, $form)->single;
229 15
        return $text;
230
    }
231
232
    public function getParent()
233
    {
234
        return $this->parent;
235
    }
236
237
    public function setParent($parent)
238
    {
239
        $this->parent = $parent;
240
    }
241
242 62
    public function getAffixes()
243
    {
244 62
        return $this->stylesRenderer->getAffixes();
245
    }
246
}
247