Passed
Pull Request — master (#64)
by
unknown
02:54
created

Date::createDateTime()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 14
nc 9
nop 1
dl 0
loc 21
ccs 15
cts 15
cp 1
crap 7
rs 8.8333
c 0
b 0
f 0
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\Date;
11
12
use Seboettg\CiteProc\CiteProc;
13
use Seboettg\CiteProc\Exception\CiteProcException;
14
use Seboettg\CiteProc\Styles\AffixesTrait;
15
use Seboettg\CiteProc\Styles\DisplayTrait;
16
use Seboettg\CiteProc\Styles\FormattingTrait;
17
use Seboettg\CiteProc\Styles\TextCaseTrait;
18
use Seboettg\CiteProc\Util;
19
use Seboettg\Collection\ArrayList;
20
21
22
/**
23
 * Class Date
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 Date
29
{
30
31
    use AffixesTrait,
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\Date\Date.
Loading history...
32
        DisplayTrait,
33
        FormattingTrait,
34
        TextCaseTrait;
35
36
    // ymd
37
    const DATE_RANGE_STATE_NONE         = 0; // 000
38
    const DATE_RANGE_STATE_DAY          = 1; // 001
39
    const DATE_RANGE_STATE_MONTH        = 2; // 010
40
    const DATE_RANGE_STATE_MONTHDAY     = 3; // 011
41
    const DATE_RANGE_STATE_YEAR         = 4; // 100
42
    const DATE_RANGE_STATE_YEARDAY      = 5; // 101
43
    const DATE_RANGE_STATE_YEARMONTH    = 6; // 110
44
    const DATE_RANGE_STATE_YEARMONTHDAY = 7; // 111
45
46
    private static $localizedDateFormats = [
0 ignored issues
show
Coding Style introduced by
Private member variable "localizedDateFormats" must be prefixed with an underscore
Loading history...
47
        'numeric',
48
        'text'
49
    ];
50
51
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
52
     * @var ArrayList
53
     */
54
    private $dateParts;
0 ignored issues
show
Coding Style introduced by
Private member variable "dateParts" must be prefixed with an underscore
Loading history...
55
56
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
57
     * @var string
58
     */
59
    private $form = "";
0 ignored issues
show
Coding Style introduced by
Private member variable "form" must be prefixed with an underscore
Loading history...
60
61
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
62
     * @var string
63
     */
64
    private $variable = "";
0 ignored issues
show
Coding Style introduced by
Private member variable "variable" must be prefixed with an underscore
Loading history...
65
66
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
67
     * @var string
68
     */
69
    private $datePartsAttribute = "";
0 ignored issues
show
Coding Style introduced by
Private member variable "datePartsAttribute" must be prefixed with an underscore
Loading history...
70
71
    /**
72
     * Date constructor.
73
     * @param \SimpleXMLElement $node
3 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...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
74
     * @throws \Seboettg\CiteProc\Exception\InvalidStylesheetException
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
75
     */
76 56
    public function __construct(\SimpleXMLElement $node)
77
    {
78 56
        $this->dateParts = new ArrayList();
79
80
        /** @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...
81 56
        foreach ($node->attributes() as $attribute) {
82 56
            switch ($attribute->getName()) {
83 56
                case 'form':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
84 27
                    $this->form = (string) $attribute;
85 27
                    break;
86 56
                case 'variable':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
87 56
                    $this->variable = (string) $attribute;
88 56
                    break;
89 34
                case 'date-parts':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
90 56
                    $this->datePartsAttribute = (string) $attribute;
91
            }
92
        }
93
        /** @var \SimpleXMLElement $child */
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...
94 56
        foreach ($node->children() as $child) {
95 43
            if ($child->getName() === "date-part") {
96 43
                $datePartName = (string) $child->attributes()["name"];
97 43
                $this->dateParts->set($this->form . "-" . $datePartName, Util\Factory::create($child));
98
            }
99
        }
100
101 56
        $this->initAffixesAttributes($node);
102 56
        $this->initDisplayAttributes($node);
103 56
        $this->initFormattingAttributes($node);
104 56
        $this->initTextCaseAttributes($node);
105 56
    }
106
107
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $data should have a doc-comment as per coding-style.
Loading history...
108
     * @param $data
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
109
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
110
     * @throws \Seboettg\CiteProc\Exception\InvalidStylesheetException
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
111
     * @throws \Exception
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
112
     */
113 49
    public function render($data)
114
    {
115 49
        $ret = "";
116 49
        $var = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $var is dead and can be removed.
Loading history...
117 49
        if (isset($data->{$this->variable})) {
118 48
            $var = $data->{$this->variable};
119
        } else {
120 7
            return "";
121
        }
122
123
        try {
124 48
            $this->prepareDatePartsInVariable($data, $var);
125 1
        } catch (CiteProcException $e) {
126 1
            if (!preg_match("/(\p{L}+)\s?([\-\-\&,])\s?(\p{L}+)/u", $data->{$this->variable}->raw)) {
127 1
                return $this->addAffixes($this->format($this->applyTextCase($data->{$this->variable}->raw)));
128
            }
129
        }
130
131 48
        $form = $this->form;
132 48
        $dateParts = !empty($this->datePartsAttribute) ? explode("-", $this->datePartsAttribute) : [];
133 48
        $this->prepareDatePartsChildren($dateParts, $form);
134
135
136
        // No date-parts in date-part attribute defined, take into account that the defined date-part children will be used.
137 48
        if (empty($this->datePartsAttribute) && $this->dateParts->count() > 0) {
138
            /** @var DatePart $part */
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...
139 36
            foreach ($this->dateParts as $part) {
140 36
                $dateParts[] = $part->getName();
141
            }
142
        }
143
144
        /* cs:date may have one or more cs:date-part child elements (see Date-part). The attributes set on
145
        these elements override those specified for the localized date formats (e.g. to get abbreviated months for all
146
        locales, the form attribute on the month-cs:date-part element can be set to “short”). These cs:date-part
147
        elements do not affect which, or in what order, date parts are rendered. Affixes, which are very
148
        locale-specific, are not allowed on these cs:date-part elements. */
149
150 48
        if ($this->dateParts->count() > 0) {
151
152
            /* if (isset($var->raw) && !preg_match("/(\p{L}+)\s?([\-\-\&,])\s?(\p{L}+)/u", $var->raw) && $this->dateParts->count() > 0) {
153
                //$var->{"date-parts"} = [];
154
            } else*/
155 47
            if (!isset($var->{'date-parts'})) { // ignore empty date-parts
156
                return "";
157
            }
158
159 47
            if (count($data->{$this->variable}->{'date-parts'}) === 1) {
160 46
                $data_ = $this->createDateTime($data->{$this->variable}->{'date-parts'});
161
                /** @var DatePart $datePart */
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...
162 46
                foreach ($this->dateParts as $key => $datePart) {
163
                    /** @noinspection PhpUnusedLocalVariableInspection */
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...
164 46
                    list($f, $p) = explode("-", $key);
165 46
                    if (in_array($p, $dateParts)) {
166 46
                        $ret .= $datePart->render($data_[0], $this);
167
                    }
168
                }
169 2
            } else if (count($var->{'date-parts'}) === 2) { //date range
170 2
                $data_ = $this->createDateTime($var->{'date-parts'});
171 2
                $from = $data_[0];
172 2
                $to = $data_[1];
173 2
                $interval = $to->diff($from);
174 2
                $delim = "";
175 2
                $toRender = 0;
176 2
                if ($interval->y > 0 && in_array('year', $dateParts)) {
177 1
                    $toRender |= self::DATE_RANGE_STATE_YEAR;
178 1
                    $delim = $this->dateParts->get($this->form . "-year")->getRangeDelimiter();
179
                }
180 2
                if ($interval->m > 0 && $from->getMonth() - $to->getMonth() !== 0 && in_array('month', $dateParts)) {
181 1
                    $toRender |= self::DATE_RANGE_STATE_MONTH;
182 1
                    $delim = $this->dateParts->get($this->form . "-month")->getRangeDelimiter();
183
                }
184 2
                if ($interval->d > 0 && $from->getDay() - $to->getDay() !== 0 && in_array('day', $dateParts)) {
185 1
                    $toRender |= self::DATE_RANGE_STATE_DAY;
186 1
                    $delim = $this->dateParts->get($this->form . "-day")->getRangeDelimiter();
187
                }
188 2
                if ($toRender === self::DATE_RANGE_STATE_NONE) {
189 1
                    foreach ($this->dateParts as $key => $datePart) {
190
                        /** @noinspection PhpUnusedLocalVariableInspection */
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...
191 1
                        list($f, $p) = explode("-", $key);
192 1
                        if (in_array($p, $dateParts)) {
193 1
                            $ret .= $datePart->render($data_[0], $this);
194
                        }
195
                    }
196
                } else {
197 1
                      $ret = $this->renderDateRange($toRender, $from, $to, $delim);
198
                }
199
            }
200
201 47
            if (isset($var->raw) && preg_match("/(\p{L}+)\s?([\-\-\&,])\s?(\p{L}+)/u", $var->raw, $matches)) {
202
                return $matches[1] . $matches[2] . $matches[3];
203
            }
204
        }
205
        // fallback:
206
        // When there are no dateParts children, but date-parts attribute in date
207
        // render numeric
208 1
        else if (!empty($this->datePartsAttribute)) {
0 ignored issues
show
Coding Style introduced by
Expected "} else if (...) \n"; found "\n // fallback:\n // When there are no dateParts children, but date-parts attribute in date\n // render numeric\n else if (...) {\n"
Loading history...
209 1
            $data = $this->createDateTime($var->{'date-parts'});
210 1
            $ret = $this->renderNumeric($data[0]);
211
        }
212
213 48
        return !empty($ret) ? $this->addAffixes($this->format($this->applyTextCase($ret))) : "";
214
    }
215
216
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
217
     * @param array $dates
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
218
     * @return array
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
219
     * @throws \Exception
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
220
     */
221 48
    private function createDateTime($dates)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::createDateTime" must be prefixed with an underscore
Loading history...
222
    {
223 48
        $data = [];
224 48
        foreach ($dates as $date) {
225 48
            $date = $this->cleanDate($date);
226 48
            if ($date[0] < 1000) {
227 1
                $dateTime = new DateTime(0, 0, 0);
228 1
                $dateTime->setDay(0)->setMonth(0)->setYear(0);
229 1
                $data[] = $dateTime;
230
            }
231 48
            $dateTime = new DateTime($date[0], array_key_exists(1, $date) ? $date[1] : 1, array_key_exists(2, $date) ? $date[2] : 1);
232 48
            if (!array_key_exists(1, $date)) {
233 26
                $dateTime->setMonth(0);
234
            }
235 48
            if (!array_key_exists(2, $date)) {
236 31
                $dateTime->setDay(0);
237
            }
238 48
            $data[] = $dateTime;
239
        }
240
241 48
        return $data;
242
    }
243
244
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $delim should have a doc-comment as per coding-style.
Loading history...
245
     * @param integer $differentParts
3 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
246
     * @param DateTime $from
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
247
     * @param DateTime $to
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
248
     * @param $delim
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
249
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
250
     */
251 1
    private function renderDateRange($differentParts, DateTime $from, DateTime $to, $delim)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::renderDateRange" must be prefixed with an underscore
Loading history...
252
    {
253 1
        $ret = "";
254 1
        $dateParts_ = [];
255
        switch ($differentParts) {
256 1
            case self::DATE_RANGE_STATE_YEAR:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
257 1
                foreach ($this->dateParts as $key => $datePart) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
258 1
                    if (strpos($key, "year") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
259 1
                        $ret .= $this->renderOneRangePart($datePart, $from, $to, $delim);
260
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
261 1
                    if (strpos($key, "month") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
262 1
                        $day = !empty($d = $from->getMonth()) ? $d : "";
263 1
                        $ret .= $day;
264
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
265 1
                    if (strpos($key, "day") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
266 1
                        $day = !empty($d = $from->getDay()) ? $datePart->render($from, $this) : "";
0 ignored issues
show
Unused Code introduced by
The assignment to $d is dead and can be removed.
Loading history...
267 1
                        $ret .= $day;
268
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
269
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
270 1
                break;
271 1
            case self::DATE_RANGE_STATE_MONTH:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
272
                /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
273
                 * @var string $key
274
                 * @var DatePart $datePart
275
                 */
276 1
                foreach ($this->dateParts as $key => $datePart) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
277 1
                    if (strpos($key, "year") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
278 1
                        $ret .= $datePart->render($from, $this);
279
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
280 1
                    if (strpos($key, "month")) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
281 1
                        $ret .= $this->renderOneRangePart($datePart, $from, $to, $delim);
282
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
283 1
                    if (strpos($key, "day") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
284 1
                        $day = !empty($d = $from->getDay()) ? $datePart->render($from, $this) : "";
285 1
                        $ret .= $day;
286
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
287
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
288 1
                break;
289 1
            case self::DATE_RANGE_STATE_DAY:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
290
                /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
291
                 * @var string $key
292
                 * @var DatePart $datePart
293
                 */
294 1
                foreach ($this->dateParts as $key => $datePart) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
295 1
                    if (strpos($key, "year") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
296 1
                        $ret .= $datePart->render($from, $this);
297
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
298 1
                    if (strpos($key, "month") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
299 1
                        $ret .= $datePart->render($from, $this);
300
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
301 1
                    if (strpos($key, "day")) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
302 1
                        $ret .= $this->renderOneRangePart($datePart, $from, $to, $delim);
303
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
304
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
305 1
                break;
306 1
            case self::DATE_RANGE_STATE_YEARMONTHDAY:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
307 1
                $i = 0;
308 1
                foreach ($this->dateParts as $datePart) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
309 1
                    if ($i === $this->dateParts->count() - 1) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
310 1
                        $ret .= $datePart->renderPrefix();
311 1
                        $ret .= $datePart->renderWithoutAffixes($from, $this);
312
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
313 1
                        $ret .= $datePart->render($from, $this);
314
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
315 1
                    ++$i;
316
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
317 1
                $ret .= $delim;
318 1
                $i = 0;
319 1
                foreach ($this->dateParts as $datePart) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
320 1
                    if ($i == 0) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
321 1
                        $ret .= $datePart->renderWithoutAffixes($to, $this);
322 1
                        $ret .= $datePart->renderSuffix();
323
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
324 1
                        $ret .= $datePart->render($to, $this);
325
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
326 1
                    ++$i;
327
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
328 1
                break;
329 1
            case self::DATE_RANGE_STATE_YEARMONTH:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
330 1
                $dp = $this->dateParts->toArray();
331 1
                $i = 0;
332 1
                $dateParts_ = [];
333 1
                array_walk($dp, function($datePart, $key) use (&$i, &$dateParts_, $differentParts) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
Unused Code introduced by
The import $differentParts is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
Unused Code introduced by
The import $i is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
334 1
                    if (strpos($key, "year") !== false || strpos($key, "month") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
335 1
                        $dateParts_["yearmonth"][] = $datePart;
336
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
337 1
                    if (strpos($key, "day") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
338 1
                        $dateParts_["day"] = $datePart;
339
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
340 1
                });
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
341 1
                break;
342 1
            case self::DATE_RANGE_STATE_YEARDAY:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
343
                $dp = $this->dateParts->toArray();
344
                $i = 0;
345
                $dateParts_ = [];
346
                array_walk($dp, function($datePart, $key) use (&$i, &$dateParts_, $differentParts) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
Unused Code introduced by
The import $i is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
Unused Code introduced by
The import $differentParts is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
347
                    if (strpos($key, "year") !== false || strpos($key, "day") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
348
                        $dateParts_["yearday"][] = $datePart;
349
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
350
                    if (strpos($key, "month") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
351
                        $dateParts_["month"] = $datePart;
352
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
353
                });
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
354
                break;
355 1
            case self::DATE_RANGE_STATE_MONTHDAY:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
356 1
                $dp = $this->dateParts->toArray();
357 1
                $i = 0;
358 1
                $dateParts_ = [];
359 1
                array_walk($dp, function($datePart, $key) use (&$i, &$dateParts_, $differentParts) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
Unused Code introduced by
The import $differentParts is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
Unused Code introduced by
The import $i is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
360
                    //$bit = sprintf("%03d", decbin($differentParts));
361 1
                    if (strpos($key, "month") !== false || strpos($key, "day") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
362 1
                        $dateParts_["monthday"][] = $datePart;
363
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
364 1
                    if (strpos($key, "year") !== false) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
365 1
                        $dateParts_["year"] = $datePart;
366
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
367 1
                });
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
368 1
                break;
369
        }
370
        switch ($differentParts) {
371 1
            case self::DATE_RANGE_STATE_YEARMONTH:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
372 1
            case self::DATE_RANGE_STATE_YEARDAY:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
373 1
            case self::DATE_RANGE_STATE_MONTHDAY:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
374
                /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
375
                 * @var $key
376
                 * @var DatePart $datePart */
1 ignored issue
show
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
377 1
                foreach ($dateParts_ as $key => $datePart) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
378 1
                    if (is_array($datePart)) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
379
380 1
                        $f  = $datePart[0]->render($from, $this);
381 1
                        $f .= $datePart[1]->renderPrefix();
382 1
                        $f .= $datePart[1]->renderWithoutAffixes($from, $this);
383 1
                        $t  = $datePart[0]->renderWithoutAffixes($to, $this);
384 1
                        $t .= $datePart[0]->renderSuffix();
385 1
                        $t .= $datePart[1]->render($to, $this);
386 1
                        $ret .= $f . $delim . $t;
387
                    } else {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
388 1
                        $ret .= $datePart->render($from, $this);
389
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
390
                }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
391 1
                break;
392
        }
393 1
        return $ret;
394
    }
395
396
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $datePart should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $delim should have a doc-comment as per coding-style.
Loading history...
397
     * @param $datePart
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
398
     * @param DateTime $from
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
399
     * @param DateTime $to
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
400
     * @param $delim
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
401
     * @return string
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
402
     */
403 1
    protected function renderOneRangePart(DatePart $datePart, $from, $to, $delim)
404
    {
405 1
        $prefix = $datePart->renderPrefix();
406 1
        $from = $datePart->renderWithoutAffixes($from, $this);
407 1
        $to = $datePart->renderWithoutAffixes($to, $this);
408 1
        $suffix = !empty($to) ? $datePart->renderSuffix() : "";
409 1
        return $prefix . $from . $delim . $to . $suffix;
410
    }
411
412
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
413
     * @param string $format
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
414
     * @return bool
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
415
     */
416 15
    private function hasDatePartsFromLocales($format)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::hasDatePartsFromLocales" must be prefixed with an underscore
Loading history...
417
    {
418 15
        $dateXml = CiteProc::getContext()->getLocale()->getDateXml();
419 15
        return !empty($dateXml[$format]);
420
    }
421
422
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
423
     * @param string $format
2 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
424
     * @return array
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
425
     */
426 15
    private function getDatePartsFromLocales($format)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::getDatePartsFromLocales" must be prefixed with an underscore
Loading history...
427
    {
428 15
        $ret = [];
429
        // date parts from locales
430 15
        $dateFromLocale_ = CiteProc::getContext()->getLocale()->getDateXml();
431 15
        $dateFromLocale = $dateFromLocale_[$format];
432
433
        // no custom date parts within the date element (this)?
434 15
        if (!empty($dateFromLocale)) {
435
436 15
            $dateForm = array_filter(is_array($dateFromLocale) ? $dateFromLocale : [$dateFromLocale], function($element) use ($format) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
437
                /** @var \SimpleXMLElement $element */
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...
438 15
                $dateForm = (string) $element->attributes()["form"];
439 15
                return $dateForm === $format;
440 15
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
441
442
            //has dateForm from locale children (date-part elements)?
443 15
            $localeDate = array_pop($dateForm);
444
445 15
            if ($localeDate instanceof \SimpleXMLElement && $localeDate->count() > 0) {
446 15
                foreach ($localeDate as $child) {
447 15
                    $ret[] = $child;
448
                }
449
            }
450
        }
451 15
        return $ret;
452
    }
453
454
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
455
     * @return string
456
     */
457 26
    public function getVariable()
458
    {
459 26
        return $this->variable;
460
    }
461
462
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $data should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $var should have a doc-comment as per coding-style.
Loading history...
463
     * @param $data
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
464
     * @param $var
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
465
     * @throws CiteProcException
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
466
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
467 48
    private function prepareDatePartsInVariable($data, $var)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::prepareDatePartsInVariable" must be prefixed with an underscore
Loading history...
468
    {
469 48
        if (!isset($data->{$this->variable}->{'date-parts'}) || empty($data->{$this->variable}->{'date-parts'})) {
470 4
            if (isset($data->{$this->variable}->raw) && !empty($data->{$this->variable}->raw)) {
471
                //try {
472
                // try to parse date parts from "raw" attribute
473 4
                $var->{'date-parts'} = Util\DateHelper::parseDateParts($data->{$this->variable});
474
                //} catch (CiteProcException $e) {
475
                //    if (!preg_match("/(\p{L}+)\s?([\-\-\&,])\s?(\p{L}+)/u", $data->{$this->variable}->raw)) {
476
                //        return $this->addAffixes($this->format($this->applyTextCase($data->{$this->variable}->raw)));
477
                //    }
478
                //}
479
            } else {
480
                throw new CiteProcException("No valid date format");
481
                //return "";
482
            }
483
        }
484 48
    }
485
486
    /**
1 ignored issue
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $dateParts should have a doc-comment as per coding-style.
Loading history...
487
     * @param $dateParts
1 ignored issue
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
488
     * @param string $form
3 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
489
     * @throws \Seboettg\CiteProc\Exception\InvalidStylesheetException
1 ignored issue
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
490
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
491 48
    private function prepareDatePartsChildren($dateParts, $form)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::prepareDatePartsChildren" must be prefixed with an underscore
Loading history...
492
    {
493
        /* Localized date formats are selected with the optional form attribute, which must set to either “numeric”
494
        (for fully numeric formats, e.g. “12-15-2005”), or “text” (for formats with a non-numeric month, e.g.
495
        “December 15, 2005”). Localized date formats can be customized in two ways. First, the date-parts attribute may
496
        be used to show fewer date parts. The possible values are:
497
            - “year-month-day” - (default), renders the year, month and day
498
            - “year-month” - renders the year and month
499
            - “year” - renders the year */
500
501 48
        if ($this->dateParts->count() < 1 && in_array($form, self::$localizedDateFormats)) {
502 15
            if ($this->hasDatePartsFromLocales($form)) {
503 15
                $datePartsFromLocales = $this->getDatePartsFromLocales($form);
504 15
                array_filter($datePartsFromLocales, function(\SimpleXMLElement $item) use ($dateParts) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
505 15
                    return in_array($item["name"], $dateParts);
506 15
                });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
507
508 15
                foreach ($datePartsFromLocales as $datePartNode) {
509 15
                    $datePart = $datePartNode["name"];
510 15
                    $this->dateParts->set("$form-$datePart", Util\Factory::create($datePartNode));
511
                }
512
            } else { //otherwise create default date parts
513
                foreach ($dateParts as $datePart) {
514
                    $this->dateParts->add("$form-$datePart", new DatePart(new \SimpleXMLElement('<date-part name="' . $datePart . '" form="' . $form . '" />')));
515
                }
516
            }
517
        }
518 48
    }
519
520
521 1
    private function renderNumeric(DateTime $date)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::renderNumeric" must be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing doc comment for function renderNumeric()
Loading history...
522
    {
523 1
        return $date->renderNumeric();
524
    }
525
526 11
    public function getForm()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getForm()
Loading history...
527
    {
528 11
        return $this->form;
529
    }
530
531 48
    private function cleanDate($date)
1 ignored issue
show
Coding Style introduced by
Private method name "Date::cleanDate" must be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing doc comment for function cleanDate()
Loading history...
532
    {
533 48
        $ret = [];
534 48
        foreach ($date as $key => $datePart) {
535 48
            $ret[$key] = Util\NumberHelper::extractNumber(Util\StringHelper::removeBrackets($datePart));
536
        }
537 48
        return $ret;
538
    }
539
}