Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Egulias\EmailValidator\Parser;
4
 
5
use Egulias\EmailValidator\EmailLexer;
6
use Egulias\EmailValidator\Result\Result;
7
use Egulias\EmailValidator\Result\ValidEmail;
8
use Egulias\EmailValidator\Result\InvalidEmail;
9
use Egulias\EmailValidator\Warning\LocalTooLong;
10
use Egulias\EmailValidator\Result\Reason\DotAtEnd;
11
use Egulias\EmailValidator\Result\Reason\DotAtStart;
12
use Egulias\EmailValidator\Result\Reason\ConsecutiveDot;
13
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
14
use Egulias\EmailValidator\Parser\CommentStrategy\LocalComment;
15
 
16
class LocalPart extends PartParser
17
{
18
    public const INVALID_TOKENS = [
19
        EmailLexer::S_COMMA => EmailLexer::S_COMMA,
20
        EmailLexer::S_CLOSEBRACKET => EmailLexer::S_CLOSEBRACKET,
21
        EmailLexer::S_OPENBRACKET => EmailLexer::S_OPENBRACKET,
22
        EmailLexer::S_GREATERTHAN => EmailLexer::S_GREATERTHAN,
23
        EmailLexer::S_LOWERTHAN => EmailLexer::S_LOWERTHAN,
24
        EmailLexer::S_COLON => EmailLexer::S_COLON,
25
        EmailLexer::S_SEMICOLON => EmailLexer::S_SEMICOLON,
26
        EmailLexer::INVALID => EmailLexer::INVALID
27
    ];
28
 
29
    /**
30
     * @var string
31
     */
32
    private $localPart = '';
33
 
34
 
150 lars 35
    public function parse(): Result
148 lars 36
    {
37
        $this->lexer->startRecording();
38
 
150 lars 39
        while (!$this->lexer->current->isA(EmailLexer::S_AT) && !$this->lexer->current->isA(EmailLexer::S_EMPTY)) {
148 lars 40
            if ($this->hasDotAtStart()) {
150 lars 41
                return new InvalidEmail(new DotAtStart(), $this->lexer->current->value);
148 lars 42
            }
43
 
150 lars 44
            if ($this->lexer->current->isA(EmailLexer::S_DQUOTE)) {
148 lars 45
                $dquoteParsingResult = $this->parseDoubleQuote();
46
 
47
                //Invalid double quote parsing
150 lars 48
                if ($dquoteParsingResult->isInvalid()) {
148 lars 49
                    return $dquoteParsingResult;
50
                }
51
            }
52
 
150 lars 53
            if (
54
                $this->lexer->current->isA(EmailLexer::S_OPENPARENTHESIS) ||
55
                $this->lexer->current->isA(EmailLexer::S_CLOSEPARENTHESIS)
56
            ) {
148 lars 57
                $commentsResult = $this->parseComments();
58
 
59
                //Invalid comment parsing
150 lars 60
                if ($commentsResult->isInvalid()) {
148 lars 61
                    return $commentsResult;
62
                }
63
            }
64
 
150 lars 65
            if ($this->lexer->current->isA(EmailLexer::S_DOT) && $this->lexer->isNextToken(EmailLexer::S_DOT)) {
66
                return new InvalidEmail(new ConsecutiveDot(), $this->lexer->current->value);
148 lars 67
            }
68
 
150 lars 69
            if (
70
                $this->lexer->current->isA(EmailLexer::S_DOT) &&
148 lars 71
                $this->lexer->isNextToken(EmailLexer::S_AT)
72
            ) {
150 lars 73
                return new InvalidEmail(new DotAtEnd(), $this->lexer->current->value);
148 lars 74
            }
75
 
76
            $resultEscaping = $this->validateEscaping();
77
            if ($resultEscaping->isInvalid()) {
78
                return $resultEscaping;
79
            }
80
 
81
            $resultToken = $this->validateTokens(false);
82
            if ($resultToken->isInvalid()) {
83
                return $resultToken;
84
            }
85
 
86
            $resultFWS = $this->parseLocalFWS();
150 lars 87
            if ($resultFWS->isInvalid()) {
148 lars 88
                return $resultFWS;
89
            }
90
 
91
            $this->lexer->moveNext();
92
        }
93
 
94
        $this->lexer->stopRecording();
95
        $this->localPart = rtrim($this->lexer->getAccumulatedValues(), '@');
96
        if (strlen($this->localPart) > LocalTooLong::LOCAL_PART_LENGTH) {
97
            $this->warnings[LocalTooLong::CODE] = new LocalTooLong();
98
        }
99
 
100
        return new ValidEmail();
101
    }
102
 
150 lars 103
    protected function validateTokens(bool $hasComments): Result
148 lars 104
    {
150 lars 105
        if (isset(self::INVALID_TOKENS[$this->lexer->current->type])) {
106
            return new InvalidEmail(new ExpectingATEXT('Invalid token found'), $this->lexer->current->value);
148 lars 107
        }
108
        return new ValidEmail();
109
    }
110
 
150 lars 111
    public function localPart(): string
148 lars 112
    {
113
        return $this->localPart;
114
    }
115
 
150 lars 116
    private function parseLocalFWS(): Result
148 lars 117
    {
118
        $foldingWS = new FoldingWhiteSpace($this->lexer);
119
        $resultFWS = $foldingWS->parse();
120
        if ($resultFWS->isValid()) {
121
            $this->warnings = array_merge($this->warnings, $foldingWS->getWarnings());
122
        }
123
        return $resultFWS;
124
    }
125
 
150 lars 126
    private function hasDotAtStart(): bool
148 lars 127
    {
150 lars 128
        return $this->lexer->current->isA(EmailLexer::S_DOT) && $this->lexer->getPrevious()->isA(EmailLexer::S_EMPTY);
148 lars 129
    }
130
 
150 lars 131
    private function parseDoubleQuote(): Result
148 lars 132
    {
133
        $dquoteParser = new DoubleQuote($this->lexer);
134
        $parseAgain = $dquoteParser->parse();
135
        $this->warnings = array_merge($this->warnings, $dquoteParser->getWarnings());
136
 
137
        return $parseAgain;
138
    }
139
 
140
    protected function parseComments(): Result
141
    {
142
        $commentParser = new Comment($this->lexer, new LocalComment());
143
        $result = $commentParser->parse();
144
        $this->warnings = array_merge($this->warnings, $commentParser->getWarnings());
150 lars 145
        if ($result->isInvalid()) {
148 lars 146
            return $result;
147
        }
148
        return $result;
149
    }
150
 
150 lars 151
    private function validateEscaping(): Result
148 lars 152
    {
153
        //Backslash found
150 lars 154
        if (!$this->lexer->current->isA(EmailLexer::S_BACKSLASH)) {
148 lars 155
            return new ValidEmail();
156
        }
157
 
158
        if ($this->lexer->isNextToken(EmailLexer::GENERIC)) {
150 lars 159
            return new InvalidEmail(new ExpectingATEXT('Found ATOM after escaping'), $this->lexer->current->value);
148 lars 160
        }
161
 
162
        if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
163
            return new ValidEmail();
164
        }
165
 
166
        return new ValidEmail();
167
    }
168
}