Test Failed
Pull Request — master (#203)
by
unknown
02:43
created

Parser::checkConsecutiveDots()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6

Duplication

Lines 3
Ratio 50 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 3
loc 6
ccs 4
cts 4
cp 1
rs 10
cc 3
nc 2
nop 0
crap 3
1
<?php
2
3
namespace Egulias\EmailValidator\Parser;
4
5
use Egulias\EmailValidator\EmailLexer;
6
use Egulias\EmailValidator\Exception\AtextAfterCFWS;
7
use Egulias\EmailValidator\Exception\ConsecutiveDot;
8
use Egulias\EmailValidator\Exception\CRLFAtTheEnd;
9
use Egulias\EmailValidator\Exception\CRLFX2;
10
use Egulias\EmailValidator\Exception\CRNoLF;
11
use Egulias\EmailValidator\Exception\ExpectingQPair;
12
use Egulias\EmailValidator\Exception\ExpectingATEXT;
13
use Egulias\EmailValidator\Exception\ExpectingCTEXT;
14
use Egulias\EmailValidator\Exception\UnclosedComment;
15
use Egulias\EmailValidator\Exception\UnclosedQuotedString;
16
use Egulias\EmailValidator\Warning\CFWSNearAt;
17
use Egulias\EmailValidator\Warning\CFWSWithFWS;
18
use Egulias\EmailValidator\Warning\Comment;
19
use Egulias\EmailValidator\Warning\QuotedPart;
20
use Egulias\EmailValidator\Warning\QuotedString;
21
22
abstract class Parser
23
{
24
    protected $warnings = [];
25
    protected $lexer;
26
    protected $openedParenthesis = 0;
27
28 130
    public function __construct(EmailLexer $lexer)
29
    {
30 130
        $this->lexer = $lexer;
31 130
    }
32
33 40
    public function getWarnings()
34
    {
35 40
        return $this->warnings;
36
    }
37
38
    abstract public function parse($str);
39
40
    /** @return int */
41 6
    public function getOpenedParenthesis()
42
    {
43 6
        return $this->openedParenthesis;
44
    }
45
46
    /**
47
     * validateQuotedPair
48
     */
49
    protected function validateQuotedPair()
50
    {
51 View Code Duplication
        if (!($this->lexer->token['type'] === EmailLexer::INVALID
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
52
            || $this->lexer->token['type'] === EmailLexer::C_DEL)) {
53
            throw new ExpectingQPair();
54
        }
55
56
        $previous = $this->lexer->getPrevious() ?: ['type' => null];
57
58
        $this->warnings[QuotedPart::CODE] =
59
            new QuotedPart($previous['type'], $this->lexer->token['type']);
60
    }
61
62 10
    protected function parseComments()
63
    {
64 10
        $this->openedParenthesis = 1;
65 10
        $this->isUnclosedComment();
66 6
        $this->warnings[Comment::CODE] = new Comment();
67 6
        while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
68 6
            if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) {
69 1
                $this->openedParenthesis++;
70 1
            }
71 6
            $this->warnEscaping();
72 6
            $this->lexer->moveNext();
73 6
        }
74
75 6
        $this->lexer->moveNext();
76 6
        if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) {
77
            throw new ExpectingATEXT();
78
        }
79
80 6
        if ($this->lexer->isNextToken(EmailLexer::S_AT)) {
81 1
            $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt();
82 1
        }
83 6
    }
84
85 13
    protected function isUnclosedComment()
86
    {
87
        try {
88 13
            $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS);
89 7
            return true;
90 6
        } catch (\RuntimeException $e) {
91 6
            throw new UnclosedComment();
92
        }
93
    }
94
95 16
    protected function parseFWS()
96
    {
97 16
        $previous = $this->lexer->getPrevious() ?: ['type' => null];
98
99 16
        $this->checkCRLFInFWS();
100
101 16
        if ($this->lexer->token['type'] === EmailLexer::S_CR) {
102 2
            throw new CRNoLF();
103
        }
104
105 14 View Code Duplication
        if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type']  !== EmailLexer::S_AT) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
106 7
            throw new AtextAfterCFWS();
107
        }
108
109 10 View Code Duplication
        if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
110
            throw new ExpectingCTEXT();
111
        }
112
113 10
        if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type']  === EmailLexer::S_AT) {
114 3
            $this->warnings[CFWSNearAt::CODE] = new CFWSNearAt();
115 3
        } else {
116 8
            $this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
117
        }
118 10
    }
119
120 102
    protected function checkConsecutiveDots()
121
    {
122 102 View Code Duplication
        if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123 3
            throw new ConsecutiveDot();
124
        }
125 102
    }
126
127 96
    protected function isFWS()
128
    {
129 96
        if ($this->escaped()) {
130 1
            return false;
131
        }
132
133 96
        if ($this->lexer->token['type'] === EmailLexer::S_SP ||
134 96
            $this->lexer->token['type'] === EmailLexer::S_HTAB ||
135 96
            $this->lexer->token['type'] === EmailLexer::S_CR ||
136 96
            $this->lexer->token['type'] === EmailLexer::S_LF ||
137 96
            $this->lexer->token['type'] === EmailLexer::CRLF
138 96
        ) {
139 16
            return true;
140
        }
141
142 96
        return false;
143
    }
144
145 96
    protected function escaped()
146
    {
147 96
        $previous = $this->lexer->getPrevious() ?: ['type' => null];
148
149 96
        if ($previous['type'] === EmailLexer::S_BACKSLASH
150 96
            &&
151 1
            $this->lexer->token['type'] !== EmailLexer::GENERIC
152 96
        ) {
153 1
            return true;
154
        }
155
156 96
        return false;
157
    }
158
159 102
    protected function warnEscaping()
160
    {
161 102
        if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) {
162 97
            return false;
163
        }
164
165 7
        if ($this->lexer->isNextToken(EmailLexer::GENERIC)) {
166 6
            throw new ExpectingATEXT();
167
        }
168
169 1
        if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
170
            return false;
171
        }
172
173 1
        $previous = $this->lexer->getPrevious() ?: ['type' => null];
174
175 1
        $this->warnings[QuotedPart::CODE] =
176 1
            new QuotedPart($previous['type'], $this->lexer->token['type']);
177 1
        return true;
178
179
    }
180
181 126
    protected function checkDQUOTE($hasClosingQuote)
182
    {
183 126
        if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) {
184 105
            return $hasClosingQuote;
185
        }
186 22
        if ($hasClosingQuote) {
187
            return $hasClosingQuote;
188
        }
189 22
        $previous = $this->lexer->getPrevious() ?: ['type' => null];
190 22 View Code Duplication
        if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
191 1
            throw new ExpectingATEXT();
192
        }
193
194
        try {
195 21
            $this->lexer->find(EmailLexer::S_DQUOTE);
196 20
            $hasClosingQuote = true;
197 21
        } catch (\Exception $e) {
198 1
            throw new UnclosedQuotedString();
199
        }
200 20
        $this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']);
201
202
        return $hasClosingQuote;
203
    }
204
205 16
    protected function checkCRLFInFWS()
206
    {
207 16
        if ($this->lexer->token['type'] !== EmailLexer::CRLF) {
208 16
            return;
209
        }
210
211
        if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
212
            throw new CRLFX2();
213
        }
214
215
        if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
216
            throw new CRLFAtTheEnd();
217
        }
218
    }
219
}
220