Comment.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. <?php
  2. namespace Egulias\EmailValidator\Parser;
  3. use Egulias\EmailValidator\EmailLexer;
  4. use Egulias\EmailValidator\Result\Result;
  5. use Egulias\EmailValidator\Warning\QuotedPart;
  6. use Egulias\EmailValidator\Result\InvalidEmail;
  7. use Egulias\EmailValidator\Parser\CommentStrategy\CommentStrategy;
  8. use Egulias\EmailValidator\Result\Reason\UnclosedComment;
  9. use Egulias\EmailValidator\Result\Reason\UnOpenedComment;
  10. use Egulias\EmailValidator\Warning\Comment as WarningComment;
  11. class Comment extends PartParser
  12. {
  13. /**
  14. * @var int
  15. */
  16. private $openedParenthesis = 0;
  17. /**
  18. * @var CommentStrategy
  19. */
  20. private $commentStrategy;
  21. public function __construct(EmailLexer $lexer, CommentStrategy $commentStrategy)
  22. {
  23. $this->lexer = $lexer;
  24. $this->commentStrategy = $commentStrategy;
  25. }
  26. public function parse(): Result
  27. {
  28. if ($this->lexer->current->isA(EmailLexer::S_OPENPARENTHESIS)) {
  29. $this->openedParenthesis++;
  30. if ($this->noClosingParenthesis()) {
  31. return new InvalidEmail(new UnclosedComment(), $this->lexer->current->value);
  32. }
  33. }
  34. if ($this->lexer->current->isA(EmailLexer::S_CLOSEPARENTHESIS)) {
  35. return new InvalidEmail(new UnOpenedComment(), $this->lexer->current->value);
  36. }
  37. $this->warnings[WarningComment::CODE] = new WarningComment();
  38. $moreTokens = true;
  39. while ($this->commentStrategy->exitCondition($this->lexer, $this->openedParenthesis) && $moreTokens) {
  40. if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) {
  41. $this->openedParenthesis++;
  42. }
  43. $this->warnEscaping();
  44. if ($this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
  45. $this->openedParenthesis--;
  46. }
  47. $moreTokens = $this->lexer->moveNext();
  48. }
  49. if ($this->openedParenthesis >= 1) {
  50. return new InvalidEmail(new UnclosedComment(), $this->lexer->current->value);
  51. }
  52. if ($this->openedParenthesis < 0) {
  53. return new InvalidEmail(new UnOpenedComment(), $this->lexer->current->value);
  54. }
  55. $finalValidations = $this->commentStrategy->endOfLoopValidations($this->lexer);
  56. $this->warnings = [...$this->warnings, ...$this->commentStrategy->getWarnings()];
  57. return $finalValidations;
  58. }
  59. /**
  60. * @return void
  61. */
  62. private function warnEscaping(): void
  63. {
  64. //Backslash found
  65. if (!$this->lexer->current->isA(EmailLexer::S_BACKSLASH)) {
  66. return;
  67. }
  68. if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
  69. return;
  70. }
  71. $this->warnings[QuotedPart::CODE] =
  72. new QuotedPart($this->lexer->getPrevious()->type, $this->lexer->current->type);
  73. }
  74. private function noClosingParenthesis(): bool
  75. {
  76. try {
  77. $this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS);
  78. return false;
  79. } catch (\RuntimeException $e) {
  80. return true;
  81. }
  82. }
  83. }