Compare commits

...

6 Commits

Author SHA1 Message Date
Issei.M 19811e0082 MultipleValidatorWithAnd now can break out of loop when error occurs (#122)
* MultipleValidatorWithAnd now can break out of loop when error occurs

* improved logic

* updated doc

* bugfix
2016-07-12 15:22:10 +02:00
Michele Locati b366d54b0a Exclude some dirs and files from repository auto-generated ZIP archives (#113)
People that install this library via composer don't need the test stuff, they just need the library itself.
This PR removes the development directories and files from the repository auto-generated ZIP archives.
Since these development files/directories will still be available via `git clone`, Travis is happy, developers are happy, and so are end-users (they won't have unneeded stuff in production machines).
2016-07-03 23:53:17 +02:00
Issei.M 2bc46e23e5 fixed type missing and removed unused code (#117) 2016-06-25 00:47:43 +02:00
Issei.M 7701238433 fixed some problems in DNSCheckValidation (#116) 2016-06-25 00:43:29 +02:00
Issei.M afde3d3874 fixed DNSCheckValidation bug (#115) 2016-06-21 17:31:36 +02:00
Pedro Maia e9c46eed92 Fix typo (#112) 2016-05-19 00:20:10 +02:00
9 changed files with 118 additions and 28 deletions
+4
View File
@@ -0,0 +1,4 @@
/Tests export-ignore
/documentation export-ignore
/.* export-ignore
/phpunit.xml.dist
+1 -1
View File
@@ -58,7 +58,7 @@ class EmailValidator
} }
/** /**
* @return string * @return InvalidEmail
*/ */
public function getError() public function getError()
{ {
@@ -3,16 +3,12 @@
namespace Egulias\EmailValidator\Validation; namespace Egulias\EmailValidator\Validation;
use Egulias\EmailValidator\EmailLexer; use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\InvalidEmail;
use Egulias\EmailValidator\Warning\NoDNSMXRecord; use Egulias\EmailValidator\Warning\NoDNSMXRecord;
use Egulias\EmailValidator\Exception\NoDNSRecord; use Egulias\EmailValidator\Exception\NoDNSRecord;
class DNSCheckValidation implements EmailValidation class DNSCheckValidation implements EmailValidation
{ {
/**
* @var EmailParser
*/
private $parser;
/** /**
* @var array * @var array
*/ */
@@ -27,10 +23,10 @@ class DNSCheckValidation implements EmailValidation
{ {
// use the input to check DNS if we cannot extract something similar to a domain // use the input to check DNS if we cannot extract something similar to a domain
$host = $email; $host = $email;
// Arguable pattern to extract the domain. Not aiming to validate the domain nor the email // Arguable pattern to extract the domain. Not aiming to validate the domain nor the email
$pattern = "/^[a-z'0-9]+([._-][a-z'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+)+)+$/"; if (false !== $lastAtPos = strrpos($email, '@')) {
if (preg_match($pattern, $email, $result)) { $host = substr($email, $lastAtPos + 1);
$host = $this->extractHost($result);
} }
return $this->checkDNS($host); return $this->checkDNS($host);
@@ -46,16 +42,6 @@ class DNSCheckValidation implements EmailValidation
return $this->warnings; return $this->warnings;
} }
private function extractHost(array $result)
{
foreach ($result as $match) {
$onlyDomainPattern = "/^([a-z0-9]+([._-][a-z0-9]+))+$/";
if (preg_match($onlyDomainPattern, $match, $domainResult)) {
return $domainResult[0];
}
}
}
protected function checkDNS($host) protected function checkDNS($host)
{ {
$Aresult = true; $Aresult = true;
@@ -63,7 +49,7 @@ class DNSCheckValidation implements EmailValidation
if (!$MXresult) { if (!$MXresult) {
$this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord(); $this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord();
$Aresult = checkdnsrr($host, 'A'); $Aresult = checkdnsrr($host, 'A') || checkdnsrr($host, 'AAAA');
if (!$Aresult) { if (!$Aresult) {
$this->error = new NoDNSRecord(); $this->error = new NoDNSRecord();
} }
@@ -3,6 +3,7 @@
namespace Egulias\EmailValidator\Validation; namespace Egulias\EmailValidator\Validation;
use Egulias\EmailValidator\EmailLexer; use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\InvalidEmail;
interface EmailValidation interface EmailValidation
{ {
@@ -3,23 +3,60 @@
namespace Egulias\EmailValidator\Validation; namespace Egulias\EmailValidator\Validation;
use Egulias\EmailValidator\EmailLexer; use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\InvalidEmail;
use Egulias\EmailValidator\Validation\Exception\EmptyValidationList; use Egulias\EmailValidator\Validation\Exception\EmptyValidationList;
class MultipleValidationWithAnd implements EmailValidation class MultipleValidationWithAnd implements EmailValidation
{ {
/**
* If one of validations gets failure skips all succeeding validation.
* This means MultipleErrors will only contain a single error which first found.
*/
const STOP_ON_ERROR = 0;
/**
* All of validations will be invoked even if one of them got failure.
* So MultipleErrors will contain all causes.
*/
const ALLOW_ALL_ERRORS = 1;
/**
* @var EmailValidation[]
*/
private $validations = []; private $validations = [];
/**
* @var array
*/
private $warnings = []; private $warnings = [];
/**
* @var MultipleErrors
*/
private $error; private $error;
public function __construct(array $validations) /**
* @var bool
*/
private $mode;
/**
* @param EmailValidation[] $validations The validations.
* @param int $mode The validation mode (one of the constants).
*/
public function __construct(array $validations, $mode = self::ALLOW_ALL_ERRORS)
{ {
if (count($validations) == 0) { if (count($validations) == 0) {
throw new EmptyValidationList(); throw new EmptyValidationList();
} }
$this->validations = $validations; $this->validations = $validations;
$this->mode = $mode;
} }
/**
* {@inheritdoc}
*/
public function isValid($email, EmailLexer $emailLexer) public function isValid($email, EmailLexer $emailLexer)
{ {
$result = true; $result = true;
@@ -29,17 +66,32 @@ class MultipleValidationWithAnd implements EmailValidation
$result = $result && $validation->isValid($email, $emailLexer); $result = $result && $validation->isValid($email, $emailLexer);
$this->warnings = array_merge($this->warnings, $validation->getWarnings()); $this->warnings = array_merge($this->warnings, $validation->getWarnings());
$errors[] = $validation->getError(); $errors[] = $validation->getError();
if ($this->shouldStop($result)) {
break;
}
} }
$this->error = new MultipleErrors($errors); $this->error = new MultipleErrors($errors);
return $result; return $result;
} }
private function shouldStop($result)
{
return !$result && $this->mode === self::STOP_ON_ERROR;
}
/**
* {@inheritdoc}
*/
public function getError() public function getError()
{ {
return $this->error; return $this->error;
} }
/**
* {@inheritdoc}
*/
public function getWarnings() public function getWarnings()
{ {
return $this->warnings; return $this->warnings;
@@ -3,6 +3,7 @@
namespace Egulias\EmailValidator\Validation; namespace Egulias\EmailValidator\Validation;
use Egulias\EmailValidator\EmailLexer; use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\InvalidEmail;
use Egulias\EmailValidator\Validation\Error\SpoofEmail; use Egulias\EmailValidator\Validation\Error\SpoofEmail;
use \Spoofchecker; use \Spoofchecker;
+6 -3
View File
@@ -32,10 +32,10 @@ $validator->isValid("example@example.com", new RFCValidation()) //true
2. [NoWarningsRFCValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/NoRFCWarningsValidation.php) 2. [NoWarningsRFCValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/NoRFCWarningsValidation.php)
3. [DNSCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/DNSCheckValidation.php) 3. [DNSCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/DNSCheckValidation.php)
4. [SpoofCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/SpoofCheckValidation.php) 4. [SpoofCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/SpoofCheckValidation.php)
5. [MultipleValidationsWithAnd](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/MultipleValidationWithAnd.php) 5. [MultipleValidationWithAnd](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/MultipleValidationWithAnd.php)
6. [Your own validation](#how-to-extend) 6. [Your own validation](#how-to-extend)
`MultipleValidationsWithAnd` `MultipleValidationWithAnd`
It is a validation that operates over other validations performing a logical and (&&) over the result of each validation. It is a validation that operates over other validations performing a logical and (&&) over the result of each validation.
@@ -43,9 +43,12 @@ It is a validation that operates over other validations performing a logical and
<?php <?php
use Egulias\EmailValidator\EmailValidator; use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\DNSCheckValidation;
use Egulias\EmailValidator\Validation\MultipleValidationWithAnd;
use Egulias\EmailValidator\Validation\RFCValidation;
$validator = new EmailValidator(); $validator = new EmailValidator();
$multipleValidations = new MultipleValidationsWithAnd([ $multipleValidations = new MultipleValidationWithAnd([
new RFCValidation(), new RFCValidation(),
new DNSCheckValidation() new DNSCheckValidation()
]) ])
@@ -9,10 +9,30 @@ use Egulias\EmailValidator\Warning\NoDNSMXRecord;
class DNSCheckValidationTest extends \PHPUnit_Framework_TestCase class DNSCheckValidationTest extends \PHPUnit_Framework_TestCase
{ {
public function testValidDNS() public function validEmailsProvider()
{
return [
// dot-atom
['Abc@example.com'],
['ABC@EXAMPLE.COM'],
['Abc.123@example.com'],
['user+mailbox/department=shipping@example.com'],
['!#$%&\'*+-/=?^_`.{|}~@example.com'],
// quoted string
['"Abc@def"@example.com'],
['"Fred\ Bloggs"@example.com'],
['"Joe.\\Blow"@example.com'],
];
}
/**
* @dataProvider validEmailsProvider
*/
public function testValidDNS($validEmail)
{ {
$validation = new DNSCheckValidation(); $validation = new DNSCheckValidation();
$this->assertTrue($validation->isValid("example@example.com", new EmailLexer())); $this->assertTrue($validation->isValid($validEmail, new EmailLexer()));
} }
public function testInvalidDNS() public function testInvalidDNS()
@@ -25,7 +25,7 @@ class MultipleValidationWitAndTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* @expectedException Egulias\EmailValidator\Validation\Exception\EmptyValidationList * @expectedException \Egulias\EmailValidator\Validation\Exception\EmptyValidationList
*/ */
public function testEmptyListIsNotAllowed() public function testEmptyListIsNotAllowed()
{ {
@@ -79,4 +79,27 @@ class MultipleValidationWitAndTest extends \PHPUnit_Framework_TestCase
$multipleValidation->isValid("example@example.com", $lexer); $multipleValidation->isValid("example@example.com", $lexer);
$this->assertEquals($expectedResult, $multipleValidation->getError()); $this->assertEquals($expectedResult, $multipleValidation->getError());
} }
public function testBreakOutOfLoopWhenError()
{
$error = new CommaInDomain();
$expectedResult = new MultipleErrors([$error]);
$lexer = $this->getMock("Egulias\\EmailValidator\\EmailLexer");
$validation1 = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation1->expects($this->any())->method("isValid")->willReturn(false);
$validation1->expects($this->once())->method("getWarnings")->willReturn([]);
$validation1->expects($this->once())->method("getError")->willReturn($error);
$validation2 = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation2->expects($this->never())->method("isValid");
$validation2->expects($this->never())->method("getWarnings");
$validation2->expects($this->never())->method("getError");
$multipleValidation = new MultipleValidationWithAnd([$validation1, $validation2], MultipleValidationWithAnd::STOP_ON_ERROR);
$multipleValidation->isValid("example@example.com", $lexer);
$this->assertEquals($expectedResult, $multipleValidation->getError());
}
} }