Completed
Push — master ( 9ad54b...895d73 )
by Federico
03:21
created

Attributes::getParseFunction()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 6
c 1
b 0
f 1
nc 1
nop 8
dl 0
loc 10
rs 9.4285

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Jade\Lexer;
4
5
use Jade\Compiler\CommonUtils;
6
7
/**
8
 * Class Jade\Lexer\Attributes.
9
 */
10
class Attributes
11
{
12
    protected $token;
13
14
    public function __construct($token = null)
15
    {
16
        $this->token = $token;
17
    }
18
19
    protected function parseSpace($states, $escapedAttribute, &$key, &$val, $char, $previousNonBlankChar, $nextChar)
20
    {
21
        if (
22
            in_array($states->current(), array('expr', 'array', 'string', 'object')) ||
23
            (
24
                ($char === ' ' || $char === "\t") &&
25
                (
26
                    !preg_match('/^[a-zA-Z0-9_\\x7f-\\xff"\'\\]\\)\\}]$/', $previousNonBlankChar) ||
27
                    !preg_match('/^[a-zA-Z0-9_]$/', $nextChar)
28
                )
29
            )
30
        ) {
31
            $val .= $char;
32
33
            return;
34
        }
35
36
        $states->push('key');
37
        $val = trim($val);
38
        $key = trim($key);
39
40
        if (empty($key)) {
41
            return;
42
        }
43
44
        $key = preg_replace(
45
            array('/^[\'\"]|[\'\"]$/', '/\!/'), '', $key
46
        );
47
        $this->token->escaped[$key] = $escapedAttribute;
48
49
        $this->token->attributes[$key] = ('' === $val) ? true : $this->interpolate($val);
50
51
        $key = '';
52
        $val = '';
53
    }
54
55
    protected function replaceInterpolationsInStrings($match)
56
    {
57
        $quote = $match[1];
58
59
        return str_replace('\\#{', '#{', preg_replace_callback('/(?<!\\\\)#{([^}]+)}/', function ($match) use ($quote) {
60
            return $quote . ' . ' . CommonUtils::addDollarIfNeeded(preg_replace_callback(
61
                    '/(?<![a-zA-Z0-9_\$])(\$?[a-zA-Z_][a-zA-Z0-9_]*)\.([a-zA-Z_][a-zA-Z0-9_]*)(?![a-zA-Z0-9_])/',
62
                    function ($match) {
63
                        return CommonUtils::getGetter($match[1], $match[2]);
64
                    },
65
                    $match[1]
66
                )) . ' . ' . $quote;
67
        }, $match[0]));
68
    }
69
70
    protected function interpolate($attr)
71
    {
72
        return preg_replace_callback('/([\'"]).*?(?<!\\\\)(?:\\\\\\\\)*\1/', array($this, 'replaceInterpolationsInStrings'), $attr);
73
    }
74
75
    protected function parseEqual($states, &$escapedAttribute, &$key, &$val, $char, $previousChar)
76
    {
77
        switch ($states->current()) {
78
            case 'key char':
79
                $key .= $char;
80
                break;
81
82
            case 'val':
83
            case 'expr':
84
            case 'array':
85
            case 'string':
86
            case 'object':
87
                $val .= $char;
88
                break;
89
90
            default:
91
                $escapedAttribute = '!' !== $previousChar;
92
                $states->push('val');
93
        }
94
    }
95
96
    protected function parsePairs($states, $char, &$val)
97
    {
98
        switch ($char) {
99
            case '(':
100
                $states->pushFor('expr', 'val', 'expr');
101
                break;
102
103
            case ')':
104
                $states->popFor('val', 'expr');
105
                break;
106
107
            case '{':
108
                $states->pushFor('object', 'val');
109
                break;
110
111
            case '}':
112
                $states->popFor('object');
113
                break;
114
115
            case '[':
116
                $states->pushFor('array', 'val');
117
                break;
118
119
            case ']':
120
                $states->popFor('array');
121
                break;
122
123
            default:
124
                return false;
125
        }
126
        $val .= $char;
127
128
        return true;
129
    }
130
131
    protected function parseString(&$states, &$key, &$val, &$quote, $char)
132
    {
133
        if (($char === '"' || $char === "'") && !CommonUtils::escapedEnd($val)) {
134
            $stringParser = new StringAttribute($char);
135
            $stringParser->parse($states, $val, $quote);
136
137
            return;
138
        }
139
        ${in_array($states->current(), array('key', 'key char')) ? 'key' : 'val'} .= $char;
140
    }
141
142
    public function parseChar($char, &$nextChar, &$key, &$val, &$quote, $states, &$escapedAttribute, &$previousChar, &$previousNonBlankChar)
143
    {
144
        if ($this->parsePairs($states, $char, $val)) {
145
            return;
146
        }
147
148
        switch ($char) {
149
            case ',':
150
            case "\n":
151
            case "\t":
152
            case ' ':
153
                $this->parseSpace($states, $escapedAttribute, $key, $val, $char, $previousNonBlankChar, $nextChar);
154
                break;
155
156
            case '=':
157
                $this->parseEqual($states, $escapedAttribute, $key, $val, $char, $previousChar);
158
                break;
159
160
            default:
161
                $this->parseString($states, $key, $val, $quote, $char);
162
        }
163
    }
164
165
    protected function getParseFunction(&$key, &$val, &$quote, $states, &$escapedAttribute, &$previousChar, &$previousNonBlankChar, $parser)
166
    {
167
        return function ($char, $nextChar = '') use (&$key, &$val, &$quote, $states, &$escapedAttribute, &$previousChar, &$previousNonBlankChar, $parser) {
168
            $parser->parseChar($char, $nextChar, $key, $val, $quote, $states, $escapedAttribute, $previousChar, $previousNonBlankChar);
169
            $previousChar = $char;
170
            if (trim($char) !== '') {
171
                $previousNonBlankChar = $char;
172
            }
173
        };
174
    }
175
176
    /**
177
     * @return object
178
     */
179
    public function parseWith($str)
180
    {
181
        $parser = $this;
182
183
        $key = '';
184
        $val = '';
185
        $quote = '';
186
        $states = new AttributesState();
187
        $escapedAttribute = '';
188
        $previousChar = '';
189
        $previousNonBlankChar = '';
190
191
        $parse = $this->getParseFunction($key, $val, $quote, $states, $escapedAttribute, $previousChar, $previousNonBlankChar, $parser);
192
193
        for ($i = 0; $i < strlen($str); $i++) {
194
            $parse(substr($str, $i, 1), substr($str, $i + 1, 1));
195
        }
196
197
        $parse(',');
198
    }
199
}
200