Completed
Pull Request — master (#7)
by Harry
02:58
created

TokenStore::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
namespace Graze\CsvToken\Tokeniser\Token;
4
5
use Graze\CsvToken\Csv\Bom;
6
use Graze\CsvToken\Csv\CsvConfigurationInterface;
7
8
class TokenStore implements TokenStoreInterface
9
{
10
    /** @var array[] */
11
    private $maskStore = [];
12
    /** @var int[] */
13
    private $tokens = [];
14
    /** @var string|null */
15
    private $lastEncoding = null;
16
17
    /**
18
     * TokenStore constructor.
19
     *
20
     * @param CsvConfigurationInterface $config
21
     */
22
    public function __construct(CsvConfigurationInterface $config)
23
    {
24
        $this->tokens = $this->buildTokens($config);
25
        $this->setEncoding($config->getEncoding());
26
        $this->sort();
27
    }
28
29
    /**
30
     * @param int $mask
31
     *
32
     * @return array
33
     */
34
    public function getTokens($mask = Token::T_ANY)
35
    {
36
        if (!array_key_exists($mask, $this->maskStore)) {
37
            $this->maskStore[$mask] = array_filter($this->tokens, function ($type) use ($mask) {
38
                return $type & $mask;
39
            });
40
        }
41
42
        return $this->maskStore[$mask];
43
    }
44
45
    /**
46
     * @param CsvConfigurationInterface $config
47
     *
48
     * @return int[]
49
     */
50
    private function buildTokens(CsvConfigurationInterface $config)
51
    {
52
        $tokens = [
53
            $config->getDelimiter() => Token::T_DELIMITER,
54
        ];
55
56
        if ($config->getQuote() != '') {
57
            $tokens[$config->getQuote()] = Token::T_QUOTE;
58
            if ($config->useDoubleQuotes()) {
59
                $tokens[str_repeat($config->getQuote(), 2)] = Token::T_DOUBLE_QUOTE;
60
            }
61
        }
62
        if ($config->getEscape() != '') {
63
            $tokens[$config->getEscape()] = Token::T_ESCAPE;
64
        }
65
66
        $newLines = $config->getNewLine();
67
        if (!is_array($newLines)) {
68
            $newLines = [$newLines];
69
        }
70
        foreach ($newLines as $newLine) {
71
            $tokens[$newLine] = Token::T_NEW_LINE;
72
        }
73
        if (!is_null($config->getNullValue())) {
74
            $tokens[$config->getNullValue()] = Token::T_NULL;
75
        }
76
77
        if (is_null($config->getBom())) {
78
            $boms = [Bom::BOM_UTF8, Bom::BOM_UTF16_BE, Bom::BOM_UTF16_LE, Bom::BOM_UTF32_BE, Bom::BOM_UTF32_LE];
79
        } else {
80
            $boms = [$config->getBom()];
81
        }
82
        foreach ($boms as $bom) {
83
            $tokens[$bom] = Token::T_BOM;
84
        }
85
86
        return $tokens;
87
    }
88
89
    /**
90
     * @param string $encoding
91
     */
92
    public function setEncoding($encoding)
93
    {
94
        if ($encoding != $this->lastEncoding) {
95
            if ($this->lastEncoding) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->lastEncoding of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
96
                $changeEncoding = function ($string) use ($encoding) {
97
                    return mb_convert_encoding($string, $encoding, $this->lastEncoding);
98
                };
99
            } else {
100
                $changeEncoding = function ($string) use ($encoding) {
101
                    return mb_convert_encoding($string, $encoding);
102
                };
103
            }
104
            $tokens = [];
105
            foreach ($this->tokens as $string => $token) {
106
                if ($token != Token::T_BOM) {
107
                    $string = $changeEncoding($string);
108
                }
109
                $tokens[$string] = $token;
110
            }
111
            $this->tokens = $tokens;
112
            $this->sort();
113
114
            $this->lastEncoding = $encoding;
115
            $this->maskStore = [];
116
        }
117
    }
118
119
    /**
120
     * Sort the tokens into reverse key length order
121
     */
122
    private function sort()
123
    {
124
        // sort by reverse key length
125
        uksort($this->tokens, function ($first, $second) {
126
            return strlen($second) - strlen($first);
127
        });
128
    }
129
}
130