Part extraction improvement with lexer recording. Reported in #181

This commit is contained in:
Eduardo Gulias Davis
2020-10-03 17:37:57 +02:00
parent ce879d7d10
commit 5455d688c1
4 changed files with 125 additions and 26 deletions
+31
View File
@@ -110,6 +110,9 @@ class EmailLexer extends AbstractLexer
'position' => 0,
];
private $accumulator = '';
private $hasToRecord = false;
public function __construct()
{
$this->previous = $this->token = self::$nullToken;
@@ -169,10 +172,18 @@ class EmailLexer extends AbstractLexer
*/
public function moveNext()
{
if ($this->hasToRecord && $this->previous === self::$nullToken) {
$this->accumulator .= $this->token['value'];
}
$this->previous = $this->token;
$hasNext = parent::moveNext();
$this->token = $this->token ?: self::$nullToken;
if ($this->hasToRecord) {
$this->accumulator .= $this->token['value'];
}
return $hasNext;
}
@@ -276,4 +287,24 @@ class EmailLexer extends AbstractLexer
{
return 'iu';
}
public function getAccumulatedValues() : string
{
return $this->accumulator;
}
public function startRecording() : void
{
$this->hasToRecord = true;
}
public function stopRecording() : void
{
$this->hasToRecord = false;
}
public function clearRecorded() : void
{
$this->accumulator = '';
}
}
+34 -26
View File
@@ -12,11 +12,6 @@ use Egulias\EmailValidator\Warning\EmailTooLong;
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
use Egulias\EmailValidator\Result\Reason\NoLocalPart;
/**
* EmailParser
*
* @author Eduardo Gulias Davis <me@egulias.com>
*/
class EmailParser
{
const EMAIL_MAX_LENGTH = 254;
@@ -53,8 +48,6 @@ class EmailParser
public function __construct(EmailLexer $lexer)
{
$this->lexer = $lexer;
$this->localPartParser = new LocalPart($this->lexer);
$this->domainPartParser = new DomainPart($this->lexer);
}
/**
@@ -69,24 +62,50 @@ class EmailParser
return new InvalidEmail(new NoLocalPart(), $this->lexer->token["value"]);
}
$localPartResult = $this->localPartParser->parse();
$localPartResult = $this->processLocalPart();
if ($localPartResult->isInvalid()) {
return $localPartResult;
}
$domainPartResult = $this->domainPartParser->parse();
$domainPartResult = $this->processDomainPart();
if ($domainPartResult->isInvalid()) {
return $domainPartResult;
}
$this->setParts($str);
if ($this->lexer->hasInvalidTokens()) {
return new InvalidEmail(new ExpectingATEXT("Invalid tokens found"), $this->lexer->token["value"]);
}
$this->addLongEmailWarning($this->localPart, $this->domainPart);
return new ValidEmail();
//return array('local' => $this->localPart, 'domain' => $this->domainPart);
}
private function processLocalPart() : Result
{
$this->lexer->startRecording();
$this->localPartParser = new LocalPart($this->lexer);
$localPartResult = $this->localPartParser->parse();
$this->lexer->stopRecording();
$this->localPart = rtrim($this->lexer->getAccumulatedValues(), '@');
$this->warnings = array_merge($this->localPartParser->getWarnings(), $this->warnings);
return $localPartResult;
}
private function processDomainPart() : Result
{
$this->lexer->clearRecorded();
$this->lexer->startRecording();
$this->domainPartParser = new DomainPart($this->lexer);
$domainPartResult = $this->domainPartParser->parse();
$this->lexer->stopRecording();
$this->domainPart = $this->lexer->getAccumulatedValues();
$this->warnings = array_merge($this->domainPartParser->getWarnings(), $this->warnings);
return $domainPartResult;
}
/**
@@ -94,31 +113,20 @@ class EmailParser
*/
public function getWarnings() : array
{
$localPartWarnings = $this->localPartParser->getWarnings();
$domainPartWarnings = $this->domainPartParser->getWarnings();
$this->warnings = array_merge($localPartWarnings, $domainPartWarnings);
$this->addLongEmailWarning($this->localPart, $this->domainPart);
return $this->warnings;
}
/**
* @return string
*/
public function getParsedDomainPart() : string
public function getDomainPart() : string
{
return $this->domainPart;
}
/**
* @param string $email
*/
protected function setParts($email) : void
public function getLocalPart() : string
{
$parts = explode('@', $email);
$this->domainPart = $this->domainPartParser->getDomainPart();
$this->localPart = $parts[0];
return $this->localPart;
}
/**
+29
View File
@@ -159,4 +159,33 @@ class EmailLexerTests extends TestCase
array(chr(0), EmailLexer::C_NUL)
);
}
public function testRecordIsOffAtStart()
{
$lexer = new EmailLexer();
$lexer->setInput('foo-bar');
$lexer->moveNext();
$this->assertEquals('', $lexer->getAccumulatedValues());
}
public function testRecord()
{
$lexer = new EmailLexer();
$lexer->setInput('foo-bar');
$lexer->startRecording();
$lexer->moveNext();
$lexer->moveNext();
$this->assertEquals('foo', $lexer->getAccumulatedValues());
}
public function testRecordAndClear()
{
$lexer = new EmailLexer();
$lexer->setInput('foo-bar');
$lexer->startRecording();
$lexer->moveNext();
$lexer->moveNext();
$lexer->clearRecorded();
$this->assertEquals('', $lexer->getAccumulatedValues());
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace Egulias\EmailValidator\Tests\EmailValidator;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\EmailParser;
use PHPUnit\Framework\TestCase;
class EmailParserTests extends TestCase
{
public function emailPartsProvider()
{
return [
['test@foo.com', 'test', 'foo.com'],
['"user@name"@example.com', '"user@name"', 'example.com'],
['validipv6@[IPv6:2001:db8:1ff::a0b:dbd0]', 'validipv6', '[IPv6:2001:db8:1ff::a0b:dbd0]'],
['validipv4@[127.0.0.0]', 'validipv4', '[127.0.0.0]']
];
}
/**
* @dataProvider emailPartsProvider
*/
public function testGetParts($email, $local, $domain)
{
$parser = new EmailParser(new EmailLexer());
$parser->parse($email);
$this->assertEquals($local, $parser->getLocalPart());
$this->assertEquals($domain, $parser->getDomainPart());
}
}