Passed
Push — spaghetti ( dd673c...d276c8 )
by simpletoimplement
02:07
created

Styles::xfs()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 2
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace Spaghetti\XLSXParser;
4
5
use XMLReader;
6
7
use function in_array;
8
use function preg_match;
9
10
/**
11
 * @internal
12
 */
13
final class Styles extends AbstractXMLDictionary
14
{
15
    public const FORMAT_DATE = 1;
16
    private const FORMAT_DEFAULT = 0;
17
18
    private array $nativeDateFormats = [14, 15, 16, 17, 18, 19, 20, 21, 22, ];
19
    private array $numberFormats = [];
20
    private bool $inXfs = false;
21
22
    protected function readNext(): void
23
    {
24
        $xml = $this->getXMLReader();
25
26
        while ($xml->read()) {
27
            if ('cellXfs' === $xml->name) {
28
                switch ($xml->nodeType) {
29
                    case XMLReader::END_ELEMENT:
30
                        break 2;
31
                    case XMLReader::ELEMENT:
32
                        $this->inXfs = true;
33
                        continue 2;
34
                }
35
            }
36
37
            $this->xfs(xml: $xml);
38
        }
39
40
        $this->valid = false;
41
        $this->closeXMLReader();
42
    }
43
44
    protected function createXMLReader(): XMLReader
45
    {
46
        $xml = parent::createXMLReader();
47
        $needsRewind = false;
48
49
        while ($xml->read()) {
50
            if (XMLReader::END_ELEMENT === $xml->nodeType && 'numFmts' === $xml->name) {
51
                break;
52
            }
53
            if (XMLReader::ELEMENT === $xml->nodeType) {
54
                $this->process(xml: $xml, needsRewind: $needsRewind);
55
            }
56
        }
57
58
        if ($needsRewind) {
0 ignored issues
show
introduced by
$needsRewind is of type mixed, thus it always evaluated to false.
Loading history...
59
            $xml->close();
60
            $xml = parent::createXMLReader();
61
        }
62
63
        return $xml;
64
    }
65
66
    private function xfs(XMLReader $xml): void
67
    {
68
        if ($this->inXfs && XMLReader::ELEMENT === $xml->nodeType && 'xf' === $xml->name) {
69
            $this->values[] = $this->getValue(fmtId: (int) $xml->getAttribute(name: 'numFmtId'));
70
        }
71
    }
72
73
    private function process(XMLReader $xml, bool &$needsRewind): void
74
    {
75
        switch ($xml->name) {
76
            case 'numFmt':
77
                $this->numberFormats[$xml->getAttribute(name: 'numFmtId')] = $this->matchDateFormat(xml: $xml);
78
79
                return;
80
            case 'cellXfs':
81
                $needsRewind = true;
82
83
                return;
84
        }
85
    }
86
87
    private function matchDateFormat(XMLReader $xml): int
88
    {
89
        return preg_match(pattern: '{^(\[\$[[:alpha:]]*-[0-9A-F]*\])*[hmsdy]}i', subject: $xml->getAttribute(name: 'formatCode'), ) ? self::FORMAT_DATE : self::FORMAT_DEFAULT;
90
    }
91
92
    private function getValue(int $fmtId): int
93
    {
94
        return match (true) {
95
            in_array(needle: $fmtId, haystack: $this->nativeDateFormats, strict: true) => self::FORMAT_DATE,
96
            isset($this->numberFormats[$fmtId]) => $this->numberFormats[$fmtId],
97
            default => self::FORMAT_DEFAULT,
98
        };
99
    }
100
}
101