mirror of
https://github.com/egulias/EmailValidator.git
synced 2026-09-18 14:06:39 +00:00
code refactor (#364)
* use spread syntax instead of array_merge()
* use type cast instead of function cast
* removed redundant returns
* removed redundant phpdoc - type is already inferred
* removed invalid phpdoc - type is already inferred
The PHPDoc return type hint was incomplete, it should have been `InvalidEmail|null`, however, it can be removed altogether as the return type is already inferred from the code.
* changed warnEscaping()'s return value from bool to void
This is not a breaking change as the method is private, and it's only used at one place, where the return value was not used anyway.
* made private class property local
`private $parser` was used in only one place, hence it can be local, there is no reason to put it into the class' scope.
* removed unnecessary type casting
Concatenation already casts `static::CODE` from `int` to `string`, no reason to do it explicitly.
* removed redundant initializers - constructor overwrites them immediately
* removed redundant else block
* simplified if-else statement
* wrapped if body in brackets to comply with PSR12
* fixed README formatting
- fixed numbering at the `Available validations` section
- fixed overall formatting
* Revert "removed redundant phpdoc - type is already inferred"
This reverts commit 68a9ae20bd.
* don't wrap long lines
* make properties typed
Also using constructor property promotion, see more info about it [here](https://php.watch/versions/8.0/constructor-property-promotion).
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
A library for validating emails against several RFC.
|
||||
|
||||
## Supported RFCs ##
|
||||
## Supported RFCs
|
||||
|
||||
This library aims to support RFCs:
|
||||
|
||||
@@ -21,15 +21,15 @@ This library aims to support RFCs:
|
||||
|
||||
**Current major version with full support is v3**
|
||||
|
||||
| Version | Released | EOL | Only critical bug fixes | Full |
|
||||
| :-----: | :--------: | :---: | :---------------------: | :---: |
|
||||
| v4.x | 2023/01/07 | - | X | X |
|
||||
| v3.x | 2020/12/29 | - | X | |
|
||||
| v2.1.x | 2016/05/16 | YES | | |
|
||||
| v1.2 | 2013/19/05 | YES | | |
|
||||
| Version | Released | EOL | Only critical bug fixes | Full |
|
||||
|:-------:|:----------:|:---:|:-----------------------:|:----:|
|
||||
| v4.x | 2023/01/07 | - | X | X |
|
||||
| v3.x | 2020/12/29 | - | X | |
|
||||
| v2.1.x | 2016/05/16 | YES | | |
|
||||
| v1.2 | 2013/19/05 | YES | | |
|
||||
|
||||
|
||||
## Requirements ##
|
||||
## Requirements
|
||||
|
||||
* PHP 8.1
|
||||
* [Composer](https://getcomposer.org) is required for installation
|
||||
@@ -37,7 +37,7 @@ This library aims to support RFCs:
|
||||
|
||||
**Note**: `PHP version upgrades will happen to accomodate to the pace of major frameworks. Minor versions bumps will go via minor versions of this library (i.e: PHP7.3 -> v3.x+1). Major versions will go with major versions of the library`
|
||||
|
||||
## Installation ##
|
||||
## Installation
|
||||
|
||||
Run the command below to install via Composer
|
||||
|
||||
@@ -45,7 +45,7 @@ Run the command below to install via Composer
|
||||
composer require egulias/email-validator
|
||||
```
|
||||
|
||||
## Getting Started ##
|
||||
## Getting Started
|
||||
|
||||
`EmailValidator` requires you to decide which (or combination of them) validation/s strategy/ies you'd like to follow for each [validation](#available-validations).
|
||||
|
||||
@@ -61,14 +61,14 @@ $validator->isValid("example@example.com", new RFCValidation()); //true
|
||||
```
|
||||
|
||||
|
||||
### Available validations ###
|
||||
### Available validations
|
||||
|
||||
1. [RFCValidation](/src/Validation/RFCValidation.php): Standard RFC-like email validation.
|
||||
2. [NoRFCWarningsValidation](/src/Validation/NoRFCWarningsValidation.php): RFC-like validation that will fail when warnings* are found.
|
||||
3. [DNSCheckValidation](/src/Validation/DNSCheckValidation.php): Will check if there are DNS records that signal that the server accepts emails. This does not entail that the email exists.
|
||||
5. [MultipleValidationWithAnd](/src/Validation/MultipleValidationWithAnd.php): It is a validation that operates over other validations performing a logical and (&&) over the result of each validation.
|
||||
6. [MessageIDValidation](/src/Validation/MessageIDValidation.php): Follows [RFC2822 for message-id](https://tools.ietf.org/html/rfc2822#section-3.6.4) to validate that field, that has some differences in the domain part.
|
||||
7. [Your own validation](#how-to-extend): You can extend the library behaviour by implementing your own validations.
|
||||
4. [MultipleValidationWithAnd](/src/Validation/MultipleValidationWithAnd.php): It is a validation that operates over other validations performing a logical and (&&) over the result of each validation.
|
||||
5. [MessageIDValidation](/src/Validation/MessageIDValidation.php): Follows [RFC2822 for message-id](https://tools.ietf.org/html/rfc2822#section-3.6.4) to validate that field, that has some differences in the domain part.
|
||||
6. [Your own validation](#how-to-extend): You can extend the library behaviour by implementing your own validations.
|
||||
|
||||
*warnings: Warnings are deviations from the RFC that in a broader interpretation are accepted.
|
||||
|
||||
@@ -89,21 +89,21 @@ $multipleValidations = new MultipleValidationWithAnd([
|
||||
$validator->isValid("example@ietf.org", $multipleValidations); //true
|
||||
```
|
||||
|
||||
#### Additional validations ####
|
||||
#### Additional validations
|
||||
Validations not present in the RFCs
|
||||
|
||||
1. [SpoofCheckValidation](/src/Validation/Extra/SpoofCheckValidation.php): Will check for multi-utf-8 chars that can signal an erroneous email name.
|
||||
|
||||
|
||||
### How to extend ###
|
||||
### How to extend
|
||||
|
||||
It's easy! You just need to implement [EmailValidation](/src/Validation/EmailValidation.php) and you can use your own validation.
|
||||
|
||||
## Contributing ##
|
||||
## Contributing
|
||||
|
||||
Please follow the [Contribution guide](CONTRIBUTING.md). Is short and simple and will help a lot.
|
||||
|
||||
## Other Contributors ##
|
||||
## Other Contributors
|
||||
|
||||
(You can find current contributors [here](https://github.com/egulias/EmailValidator/graphs/contributors))
|
||||
|
||||
@@ -113,6 +113,6 @@ As this is a port from another library and work, here are other people related t
|
||||
* Josepf Bielawski [@stloyd](https://github.com/stloyd): For its first re-work of Dominic's lib
|
||||
* Dominic Sayers [@dominicsayers](https://github.com/dominicsayers): The original isemail function
|
||||
|
||||
## License ##
|
||||
## License
|
||||
|
||||
Released under the MIT License attached with this code.
|
||||
|
||||
+2
-2
@@ -56,7 +56,7 @@ class EmailParser extends Parser
|
||||
$localPartParser = new LocalPart($this->lexer);
|
||||
$localPartResult = $localPartParser->parse();
|
||||
$this->localPart = $localPartParser->localPart();
|
||||
$this->warnings = array_merge($localPartParser->getWarnings(), $this->warnings);
|
||||
$this->warnings = [...$localPartParser->getWarnings(), ...$this->warnings];
|
||||
|
||||
return $localPartResult;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ class EmailParser extends Parser
|
||||
$domainPartParser = new DomainPart($this->lexer);
|
||||
$domainPartResult = $domainPartParser->parse();
|
||||
$this->domainPart = $domainPartParser->domainPart();
|
||||
$this->warnings = array_merge($domainPartParser->getWarnings(), $this->warnings);
|
||||
$this->warnings = [...$domainPartParser->getWarnings(), ...$this->warnings];
|
||||
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class MessageIDParser extends Parser
|
||||
$localPartParser = new IDLeftPart($this->lexer);
|
||||
$localPartResult = $localPartParser->parse();
|
||||
$this->idLeft = $localPartParser->localPart();
|
||||
$this->warnings = array_merge($localPartParser->getWarnings(), $this->warnings);
|
||||
$this->warnings = [...$localPartParser->getWarnings(), ...$this->warnings];
|
||||
|
||||
return $localPartResult;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class MessageIDParser extends Parser
|
||||
$domainPartParser = new IDRightPart($this->lexer);
|
||||
$domainPartResult = $domainPartParser->parse();
|
||||
$this->idRight = $domainPartParser->domainPart();
|
||||
$this->warnings = array_merge($domainPartParser->getWarnings(), $this->warnings);
|
||||
$this->warnings = [...$domainPartParser->getWarnings(), ...$this->warnings];
|
||||
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
@@ -66,29 +66,28 @@ class Comment extends PartParser
|
||||
|
||||
$finalValidations = $this->commentStrategy->endOfLoopValidations($this->lexer);
|
||||
|
||||
$this->warnings = array_merge($this->warnings, $this->commentStrategy->getWarnings());
|
||||
$this->warnings = [...$this->warnings, ...$this->commentStrategy->getWarnings()];
|
||||
|
||||
return $finalValidations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @return void
|
||||
*/
|
||||
private function warnEscaping(): bool
|
||||
private function warnEscaping(): void
|
||||
{
|
||||
//Backslash found
|
||||
if (!$this->lexer->current->isA(EmailLexer::S_BACKSLASH)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->warnings[QuotedPart::CODE] =
|
||||
new QuotedPart($this->lexer->getPrevious()->type, $this->lexer->current->type);
|
||||
return true;
|
||||
}
|
||||
|
||||
private function noClosingParenthesis(): bool
|
||||
|
||||
@@ -12,11 +12,7 @@ class DomainComment implements CommentStrategy
|
||||
{
|
||||
public function exitCondition(EmailLexer $lexer, int $openedParenthesis): bool
|
||||
{
|
||||
if (($openedParenthesis === 0 && $lexer->isNextToken(EmailLexer::S_DOT))) { // || !$internalLexer->moveNext()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !($openedParenthesis === 0 && $lexer->isNextToken(EmailLexer::S_DOT));
|
||||
}
|
||||
|
||||
public function endOfLoopValidations(EmailLexer $lexer): Result
|
||||
|
||||
@@ -82,10 +82,10 @@ class DomainLiteral extends PartParser
|
||||
|
||||
if (!$isAddressLiteralIPv4) {
|
||||
return new ValidEmail();
|
||||
} else {
|
||||
$addressLiteral = $this->convertIPv4ToIPv6($addressLiteral);
|
||||
}
|
||||
|
||||
$addressLiteral = $this->convertIPv4ToIPv6($addressLiteral);
|
||||
|
||||
if (!$IPv6TAG) {
|
||||
$this->warnings[WarningDomainLiteral::CODE] = new WarningDomainLiteral();
|
||||
return new ValidEmail();
|
||||
|
||||
@@ -137,7 +137,7 @@ class DomainPart extends PartParser
|
||||
{
|
||||
$commentParser = new Comment($this->lexer, new DomainComment());
|
||||
$result = $commentParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $commentParser->getWarnings());
|
||||
$this->warnings = [...$this->warnings, ...$commentParser->getWarnings()];
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -213,9 +213,9 @@ class DomainPart extends PartParser
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @param Token<int, string> $token
|
||||
*
|
||||
*
|
||||
* @return Result
|
||||
*/
|
||||
private function checkNotAllowedChars(Token $token): Result
|
||||
@@ -240,14 +240,14 @@ class DomainPart extends PartParser
|
||||
|
||||
$domainLiteralParser = new DomainLiteralParser($this->lexer);
|
||||
$result = $domainLiteralParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $domainLiteralParser->getWarnings());
|
||||
$this->warnings = [...$this->warnings, ...$domainLiteralParser->getWarnings()];
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Token<int, string> $prev
|
||||
* @param bool $hasComments
|
||||
*
|
||||
*
|
||||
* @return Result
|
||||
*/
|
||||
protected function checkDomainPartExceptions(Token $prev, bool $hasComments): Result
|
||||
@@ -323,4 +323,4 @@ class DomainPart extends PartParser
|
||||
{
|
||||
return $this->domainPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ class DoubleQuote extends PartParser
|
||||
{
|
||||
|
||||
$validQuotedString = $this->checkDQUOTE();
|
||||
if ($validQuotedString->isInvalid()) return $validQuotedString;
|
||||
if ($validQuotedString->isInvalid()) {
|
||||
return $validQuotedString;
|
||||
}
|
||||
|
||||
$special = [
|
||||
EmailLexer::S_CR => true,
|
||||
@@ -56,7 +58,9 @@ class DoubleQuote extends PartParser
|
||||
|
||||
if ($prev->isA(EmailLexer::S_BACKSLASH)) {
|
||||
$validQuotedString = $this->checkDQUOTE();
|
||||
if ($validQuotedString->isInvalid()) return $validQuotedString;
|
||||
if ($validQuotedString->isInvalid()) {
|
||||
return $validQuotedString;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->lexer->isNextToken(EmailLexer::S_AT) && !$prev->isA(EmailLexer::S_BACKSLASH)) {
|
||||
|
||||
@@ -118,7 +118,7 @@ class LocalPart extends PartParser
|
||||
$foldingWS = new FoldingWhiteSpace($this->lexer);
|
||||
$resultFWS = $foldingWS->parse();
|
||||
if ($resultFWS->isValid()) {
|
||||
$this->warnings = array_merge($this->warnings, $foldingWS->getWarnings());
|
||||
$this->warnings = [...$this->warnings, ...$foldingWS->getWarnings()];
|
||||
}
|
||||
return $resultFWS;
|
||||
}
|
||||
@@ -132,7 +132,7 @@ class LocalPart extends PartParser
|
||||
{
|
||||
$dquoteParser = new DoubleQuote($this->lexer);
|
||||
$parseAgain = $dquoteParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $dquoteParser->getWarnings());
|
||||
$this->warnings = [...$this->warnings, ...$dquoteParser->getWarnings()];
|
||||
|
||||
return $parseAgain;
|
||||
}
|
||||
@@ -141,10 +141,8 @@ class LocalPart extends PartParser
|
||||
{
|
||||
$commentParser = new Comment($this->lexer, new LocalComment());
|
||||
$result = $commentParser->parse();
|
||||
$this->warnings = array_merge($this->warnings, $commentParser->getWarnings());
|
||||
if ($result->isInvalid()) {
|
||||
return $result;
|
||||
}
|
||||
$this->warnings = [...$this->warnings, ...$commentParser->getWarnings()];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -159,10 +157,6 @@ class LocalPart extends PartParser
|
||||
return new InvalidEmail(new ExpectingATEXT('Found ATOM after escaping'), $this->lexer->current->value);
|
||||
}
|
||||
|
||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ abstract class PartParser
|
||||
{
|
||||
$foldingWS = new FoldingWhiteSpace($this->lexer);
|
||||
$resultFWS = $foldingWS->parse();
|
||||
$this->warnings = array_merge($this->warnings, $foldingWS->getWarnings());
|
||||
$this->warnings = [...$this->warnings, ...$foldingWS->getWarnings()];
|
||||
return $resultFWS;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class UnusualElements implements Reason
|
||||
/**
|
||||
* @var string $element
|
||||
*/
|
||||
private $element = '';
|
||||
private $element;
|
||||
|
||||
public function __construct(string $element)
|
||||
{
|
||||
|
||||
@@ -4,25 +4,12 @@ namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
class DNSRecords
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array $records
|
||||
*/
|
||||
private $records = [];
|
||||
|
||||
/**
|
||||
* @var bool $error
|
||||
*/
|
||||
private $error = false;
|
||||
|
||||
/**
|
||||
* @param array $records
|
||||
* @param bool $error
|
||||
*/
|
||||
public function __construct(array $records, bool $error = false)
|
||||
public function __construct(private readonly array $records, private readonly bool $error = false)
|
||||
{
|
||||
$this->records = $records;
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,9 +37,6 @@ class SpoofCheckValidation implements EmailValidation
|
||||
return $this->error === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidEmail
|
||||
*/
|
||||
public function getError() : ?InvalidEmail
|
||||
{
|
||||
return $this->error;
|
||||
|
||||
@@ -22,11 +22,6 @@ class MultipleValidationWithAnd implements EmailValidation
|
||||
*/
|
||||
public const ALLOW_ALL_ERRORS = 1;
|
||||
|
||||
/**
|
||||
* @var EmailValidation[]
|
||||
*/
|
||||
private $validations = [];
|
||||
|
||||
/**
|
||||
* @var Warning[]
|
||||
*/
|
||||
@@ -37,23 +32,15 @@ class MultipleValidationWithAnd implements EmailValidation
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
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)
|
||||
public function __construct(private readonly array $validations, private readonly int $mode = self::ALLOW_ALL_ERRORS)
|
||||
{
|
||||
if (count($validations) == 0) {
|
||||
throw new EmptyValidationList();
|
||||
}
|
||||
|
||||
$this->validations = $validations;
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +53,7 @@ class MultipleValidationWithAnd implements EmailValidation
|
||||
$emailLexer->reset();
|
||||
$validationResult = $validation->isValid($email, $emailLexer);
|
||||
$result = $result && $validationResult;
|
||||
$this->warnings = array_merge($this->warnings, $validation->getWarnings());
|
||||
$this->warnings = [...$this->warnings, ...$validation->getWarnings()];
|
||||
if (!$validationResult) {
|
||||
$this->processError($validation);
|
||||
}
|
||||
|
||||
@@ -10,11 +10,6 @@ use Egulias\EmailValidator\Warning\Warning;
|
||||
|
||||
class RFCValidation implements EmailValidation
|
||||
{
|
||||
/**
|
||||
* @var EmailParser|null
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
/**
|
||||
* @var Warning[]
|
||||
*/
|
||||
@@ -27,10 +22,10 @@ class RFCValidation implements EmailValidation
|
||||
|
||||
public function isValid(string $email, EmailLexer $emailLexer): bool
|
||||
{
|
||||
$this->parser = new EmailParser($emailLexer);
|
||||
$parser = new EmailParser($emailLexer);
|
||||
try {
|
||||
$result = $this->parser->parse($email);
|
||||
$this->warnings = $this->parser->getWarnings();
|
||||
$result = $parser->parse($email);
|
||||
$this->warnings = $parser->getWarnings();
|
||||
if ($result->isInvalid()) {
|
||||
/** @psalm-suppress PropertyTypeCoercion */
|
||||
$this->error = $result;
|
||||
|
||||
@@ -48,6 +48,6 @@ abstract class Warning
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->message() . " rfc: " . $this->rfcNumber . "internal code: " . strval(static::CODE);
|
||||
return $this->message() . " rfc: " . $this->rfcNumber . "internal code: " . static::CODE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user