diff --git a/Build/phpstan/phpstan-baseline.neon b/Build/phpstan/phpstan-baseline.neon index 5e5e1b5f6c5fdd7ca22ec3bcefef0c4ee6fd8d22..ed446dc01a7c9963bbe406844318dcccffcd29a5 100644 --- a/Build/phpstan/phpstan-baseline.neon +++ b/Build/phpstan/phpstan-baseline.neon @@ -545,16 +545,6 @@ parameters: count: 1 path: ../../typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php - - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 3 - path: ../../typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php - - - - message: "#^While loop condition is always true\\.$#" - count: 3 - path: ../../typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php - - message: "#^Call to an undefined method TYPO3\\\\CMS\\\\Core\\\\Package\\\\PackageInterface\\:\\:getServiceProvider\\(\\)\\.$#" count: 1 diff --git a/composer.json b/composer.json index cef1f6c82accc7ed1211ebacc57f4ff8e64d208b..b574959656cee5a5c2d6802f9040d695167dfc63 100644 --- a/composer.json +++ b/composer.json @@ -49,11 +49,11 @@ "composer-runtime-api": "^2.1", "bacon/bacon-qr-code": "^2.0.7", "christian-riesen/base32": "^1.6", - "doctrine/annotations": "^1.13.3", + "doctrine/annotations": "^1.13.3 || ^2.0", "doctrine/dbal": "^3.5.1", - "doctrine/event-manager": "^1.1.2", - "doctrine/lexer": "^1.2.3", - "egulias/email-validator": "^3.2.1", + "doctrine/event-manager": "^2.0", + "doctrine/lexer": "^2.0 || ^3.0", + "egulias/email-validator": "^4.0", "enshrined/svg-sanitize": "^0.15.4", "firebase/php-jwt": "^6.3.1", "guzzlehttp/guzzle": "^7.5.0", diff --git a/composer.lock b/composer.lock index d123a23d2af3bfcd070210ad8c181c032c978869..f2492b51e7e7c695eaa3e1e2e8bce1afca8b2d02 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6c7c18fa5a7cd4785cb536486338f2fc", + "content-hash": "95c552d41acec33b145ec7bea700127a", "packages": [ { "name": "bacon/bacon-qr-code", @@ -491,30 +491,29 @@ }, { "name": "doctrine/event-manager", - "version": "1.2.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520" + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "conflict": { "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "~1.4.10 || ^1.8.8", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.24" + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" }, "type": "library", "autoload": { @@ -563,7 +562,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/1.2.0" + "source": "https://github.com/doctrine/event-manager/tree/2.0.0" }, "funding": [ { @@ -579,35 +578,37 @@ "type": "tidelift" } ], - "time": "2022-10-12T20:51:15+00:00" + "time": "2022-10-12T20:59:15+00:00" }, { "name": "doctrine/lexer", - "version": "1.2.3", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.0", "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9.0", + "doctrine/coding-standard": "^9 || ^10", "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -639,7 +640,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" + "source": "https://github.com/doctrine/lexer/tree/2.1.0" }, "funding": [ { @@ -655,30 +656,30 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { "name": "egulias/email-validator", - "version": "3.2.5", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "b531a2311709443320c786feb4519cfaf94af796" + "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b531a2311709443320c786feb4519cfaf94af796", - "reference": "b531a2311709443320c786feb4519cfaf94af796", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/3a85486b709bc384dae8eb78fb2eec649bdb64ff", + "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff", "shasum": "" }, "require": { - "doctrine/lexer": "^1.2|^2", - "php": ">=7.2", - "symfony/polyfill-intl-idn": "^1.15" + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" }, "require-dev": { - "phpunit/phpunit": "^8.5.8|^9.3.3", - "vimeo/psalm": "^4" + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^4.30" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -686,7 +687,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { @@ -714,7 +715,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/3.2.5" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.1" }, "funding": [ { @@ -722,7 +723,7 @@ "type": "github" } ], - "time": "2023-01-02T17:26:14+00:00" + "time": "2023-01-14T14:17:03+00:00" }, { "name": "enshrined/svg-sanitize", diff --git a/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php b/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php index bb141e9e213d47123f357b74ba4221a5e2dfac9d..2ea2174b300828d65337fcbaaee7f6b874f2367d 100644 --- a/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php +++ b/typo3/sysext/core/Classes/Database/Schema/Parser/Parser.php @@ -17,6 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Database\Schema\Parser; +use Doctrine\Common\Lexer\Token; use Doctrine\DBAL\Schema\Table; use TYPO3\CMS\Core\Database\Schema\Exception\StatementException; use TYPO3\CMS\Core\Database\Schema\Parser\AST\AbstractCreateDefinitionItem; @@ -66,22 +67,12 @@ use TYPO3\CMS\Core\Database\Schema\Parser\AST\ReferenceDefinition; /** * An LL(*) recursive-descent parser for MySQL CREATE TABLE statements. * Parses a CREATE TABLE statement, reports any errors in it, and generates an AST. + * @todo mark as internal/final */ class Parser { - /** - * The lexer. - * - * @var Lexer - */ - protected $lexer; - - /** - * The statement to parse. - * - * @var string - */ - protected $statement; + protected Lexer $lexer; + protected string $statement = ''; /** * Creates a new statement parser object. @@ -96,6 +87,7 @@ class Parser /** * Gets the lexer used by the parser. + * @todo unused. drop after recheck. */ public function getLexer(): Lexer { @@ -121,12 +113,11 @@ class Parser * * @param int $token The token type. * - * * @throws StatementException If the tokens don't match. */ - public function match($token) + public function match(int $token) { - $lookaheadType = $this->lexer->lookahead['type']; + $lookaheadType = $this->lexer->lookahead->type; // Short-circuit on first condition, usually types match if ($lookaheadType !== $token) { @@ -163,7 +154,7 @@ class Parser * @param bool $deep Whether to clean peek and reset errors. * @param int $position Position to reset. */ - public function free($deep = false, $position = 0) + public function free(bool $deep = false, int $position = 0): void { // WARNING! Use this method with care. It resets the scanner! $this->lexer->resetPosition($position); @@ -204,22 +195,21 @@ class Parser * Generates a new syntax error. * * @param string $expected Expected string. - * @param array|null $token Got token. + * @param Token|null $token Got token. * * * @throws \TYPO3\CMS\Core\Database\Schema\Exception\StatementException */ - public function syntaxError($expected = '', $token = null) + public function syntaxError(string $expected = '', ?Token $token = null): void { if ($token === null) { $token = $this->lexer->lookahead; } - - $tokenPos = $token['position'] ?? '-1'; + $tokenPos = $token->position; $message = "line 0, col {$tokenPos}: Error: "; $message .= ($expected !== '') ? "Expected {$expected}, got " : 'Unexpected '; - $message .= ($this->lexer->lookahead === null) ? 'end of string.' : "'{$token['value']}'"; + $message .= ($this->lexer->lookahead === null) ? 'end of string.' : "'{$token->value}'"; throw StatementException::syntaxError($message, StatementException::sqlError($this->statement)); } @@ -228,16 +218,17 @@ class Parser * Generates a new semantical error. * * @param string $message Optional message. - * @param array|null $token Optional token. + * @param Token|null $token Optional token. * * * @throws \TYPO3\CMS\Core\Database\Schema\Exception\StatementException */ - public function semanticalError($message = '', $token = null) + public function semanticalError(string $message = '', ?Token $token = null): void { if ($token === null) { $token = $this->lexer->lookahead ?? []; } + $tokenPos = $token->position; // Minimum exposed chars ahead of token $distance = 12; @@ -245,12 +236,11 @@ class Parser // Find a position of a final word to display in error string $createTableStatement = $this->statement; $length = strlen($createTableStatement); - $pos = $token['position'] + $distance; + $pos = $tokenPos + $distance; $pos = strpos($createTableStatement, ' ', ($length > $pos) ? $pos : $length); - $length = ($pos !== false) ? $pos - $token['position'] : $distance; + $length = ($pos !== false) ? $pos - $tokenPos : $distance; - $tokenPos = array_key_exists('position', $token) && $token['position'] > 0 ? $token['position'] : '-1'; - $tokenStr = substr($createTableStatement, $token['position'], $length); + $tokenStr = substr($createTableStatement, $tokenPos, $length); // Building informative message $message = 'line 0, col ' . $tokenPos . " near '" . $tokenStr . "': Error: " . $message; @@ -263,15 +253,15 @@ class Parser * * @param bool $resetPeek Reset peek after finding the closing parenthesis. * - * @return array + * @return Token */ - protected function peekBeyondClosingParenthesis($resetPeek = true) + protected function peekBeyondClosingParenthesis(bool $resetPeek = true): Token { $token = $this->lexer->peek(); $numUnmatched = 1; while ($numUnmatched > 0 && $token !== null) { - switch ($token['type']) { + switch ($token->type) { case Lexer::T_OPEN_PARENTHESIS: ++$numUnmatched; break; @@ -301,7 +291,7 @@ class Parser { $this->lexer->moveNext(); - if ($this->lexer->lookahead['type'] !== Lexer::T_CREATE) { + if (($this->lexer->lookahead?->type ?? null) !== Lexer::T_CREATE) { $this->syntaxError('CREATE'); } @@ -326,7 +316,7 @@ class Parser $statement = null; $this->match(Lexer::T_CREATE); - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_TEMPORARY: // Intentional fall-through case Lexer::T_TABLE: @@ -439,7 +429,7 @@ class Parser { $definitionItem = null; - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_FULLTEXT: // Intentional fall-through case Lexer::T_SPATIAL: @@ -483,7 +473,7 @@ class Parser $isUnique = false; $indexDefinition = new CreateIndexDefinitionItem(); - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_PRIMARY: $this->match(Lexer::T_PRIMARY); // KEY is a required keyword for PRIMARY index @@ -623,7 +613,7 @@ class Parser $this->match(Lexer::T_USING); - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_BTREE: $this->match(Lexer::T_BTREE); $indexType = 'BTREE'; @@ -652,14 +642,14 @@ class Parser $options = []; while ($this->lexer->lookahead && !$this->lexer->isNextTokenAny([Lexer::T_COMMA, Lexer::T_CLOSE_PARENTHESIS])) { - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_KEY_BLOCK_SIZE: $this->match(Lexer::T_KEY_BLOCK_SIZE); if ($this->lexer->isNextToken(Lexer::T_EQUALS)) { $this->match(Lexer::T_EQUALS); } $this->lexer->moveNext(); - $options['key_block_size'] = (int)$this->lexer->token['value']; + $options['key_block_size'] = (int)$this->lexer->token->value; break; case Lexer::T_USING: $options['index_type'] = $this->indexType(); @@ -672,7 +662,7 @@ class Parser case Lexer::T_COMMENT: $this->match(Lexer::T_COMMENT); $this->match(Lexer::T_STRING); - $options['comment'] = $this->lexer->token['value']; + $options['comment'] = $this->lexer->token->value; break; default: $this->syntaxError('KEY_BLOCK_SIZE, USING, WITH PARSER or COMMENT'); @@ -703,7 +693,7 @@ class Parser $columnDefinitionItem = new CreateColumnDefinitionItem($columnName, $dataType); while ($this->lexer->lookahead && !$this->lexer->isNextTokenAny([Lexer::T_COMMA, Lexer::T_CLOSE_PARENTHESIS])) { - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_NOT: $columnDefinitionItem->allowNull = false; $this->match(Lexer::T_NOT); @@ -742,7 +732,7 @@ class Parser case Lexer::T_COMMENT: $this->match(Lexer::T_COMMENT); if ($this->lexer->isNextToken(Lexer::T_STRING)) { - $columnDefinitionItem->comment = $this->lexer->lookahead['value']; + $columnDefinitionItem->comment = $this->lexer->lookahead->value; $this->match(Lexer::T_STRING); } break; @@ -824,7 +814,7 @@ class Parser { $dataType = null; - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_BIT: $this->match(Lexer::T_BIT); $dataType = new BitDataType( @@ -1015,20 +1005,20 @@ class Parser * @return mixed * @throws \TYPO3\CMS\Core\Database\Schema\Exception\StatementException */ - protected function columnDefaultValue() + protected function columnDefaultValue(): mixed { $this->match(Lexer::T_DEFAULT); $value = null; - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_INTEGER: - $value = (int)$this->lexer->lookahead['value']; + $value = (int)$this->lexer->lookahead->value; break; case Lexer::T_FLOAT: - $value = (float)$this->lexer->lookahead['value']; + $value = (float)$this->lexer->lookahead->value; break; case Lexer::T_STRING: - $value = (string)$this->lexer->lookahead['value']; + $value = (string)$this->lexer->lookahead->value; break; case Lexer::T_CURRENT_TIMESTAMP: $value = 'CURRENT_TIMESTAMP'; @@ -1061,7 +1051,7 @@ class Parser } $this->match(Lexer::T_OPEN_PARENTHESIS); - $length = (int)$this->lexer->lookahead['value']; + $length = (int)$this->lexer->lookahead->value; $this->match(Lexer::T_INTEGER); $this->match(Lexer::T_CLOSE_PARENTHESIS); @@ -1081,12 +1071,12 @@ class Parser } $this->match(Lexer::T_OPEN_PARENTHESIS); - $options['length'] = (int)$this->lexer->lookahead['value']; + $options['length'] = (int)$this->lexer->lookahead->value; $this->match(Lexer::T_INTEGER); if ($this->lexer->isNextToken(Lexer::T_COMMA)) { $this->match(Lexer::T_COMMA); - $options['decimals'] = (int)$this->lexer->lookahead['value']; + $options['decimals'] = (int)$this->lexer->lookahead->value; $this->match(Lexer::T_INTEGER); } @@ -1109,7 +1099,7 @@ class Parser } while ($this->lexer->isNextTokenAny([Lexer::T_UNSIGNED, Lexer::T_ZEROFILL])) { - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_UNSIGNED: $this->match(Lexer::T_UNSIGNED); $options['unsigned'] = true; @@ -1158,7 +1148,7 @@ class Parser } while ($this->lexer->isNextTokenAny([Lexer::T_CHARACTER, Lexer::T_COLLATE, Lexer::T_BINARY])) { - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_BINARY: $this->match(Lexer::T_BINARY); $options['binary'] = true; @@ -1167,12 +1157,12 @@ class Parser $this->match(Lexer::T_CHARACTER); $this->match(Lexer::T_SET); $this->match(Lexer::T_STRING); - $options['charset'] = $this->lexer->token['value']; + $options['charset'] = $this->lexer->token->value; break; case Lexer::T_COLLATE: $this->match(Lexer::T_COLLATE); $this->match(Lexer::T_STRING); - $options['collation'] = $this->lexer->token['value']; + $options['collation'] = $this->lexer->token->value; break; default: $this->syntaxError('BINARY, CHARACTER SET or COLLATE'); @@ -1196,17 +1186,17 @@ class Parser } while ($this->lexer->isNextTokenAny([Lexer::T_CHARACTER, Lexer::T_COLLATE])) { - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_CHARACTER: $this->match(Lexer::T_CHARACTER); $this->match(Lexer::T_SET); $this->match(Lexer::T_STRING); - $options['charset'] = $this->lexer->token['value']; + $options['charset'] = $this->lexer->token->value; break; case Lexer::T_COLLATE: $this->match(Lexer::T_COLLATE); $this->match(Lexer::T_STRING); - $options['collation'] = $this->lexer->token['value']; + $options['collation'] = $this->lexer->token->value; break; default: $this->syntaxError('CHARACTER SET or COLLATE'); @@ -1247,7 +1237,7 @@ class Parser { $this->match(Lexer::T_STRING); - return (string)$this->lexer->token['value']; + return (string)$this->lexer->token->value; } /** @@ -1277,10 +1267,10 @@ class Parser $referenceDefinition = new ReferenceDefinition($tableName, $referenceColumns); while (!$this->lexer->isNextTokenAny([Lexer::T_COMMA, Lexer::T_CLOSE_PARENTHESIS])) { - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_MATCH: $this->match(Lexer::T_MATCH); - $referenceDefinition->match = $this->lexer->lookahead['value']; + $referenceDefinition->match = $this->lexer->lookahead->value; $this->lexer->moveNext(); break; case Lexer::T_ON: @@ -1332,7 +1322,7 @@ class Parser { $action = null; - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_RESTRICT: $this->match(Lexer::T_RESTRICT); $action = 'RESTRICT'; @@ -1394,7 +1384,7 @@ class Parser $options = []; while ($this->lexer->lookahead && !$this->lexer->isNextToken(Lexer::T_SEMICOLON)) { - switch ($this->lexer->lookahead['type']) { + switch ($this->lexer->lookahead->type) { case Lexer::T_DEFAULT: // DEFAULT prefix is optional for COLLATE/CHARACTER SET, do nothing $this->match(Lexer::T_DEFAULT); @@ -1546,7 +1536,7 @@ class Parser * @return mixed * @throws \TYPO3\CMS\Core\Database\Schema\Exception\StatementException */ - protected function tableOptionValue() + protected function tableOptionValue(): mixed { // Skip the optional equals sign if ($this->lexer->isNextToken(Lexer::T_EQUALS)) { @@ -1554,7 +1544,7 @@ class Parser } $this->lexer->moveNext(); - return $this->lexer->token['value']; + return $this->lexer->token->value; } /** @@ -1564,9 +1554,9 @@ class Parser * @return \TYPO3\CMS\Core\Database\Schema\Parser\AST\Identifier * @throws \TYPO3\CMS\Core\Database\Schema\Exception\StatementException */ - protected function schemaObjectName() + protected function schemaObjectName(): Identifier { - $schemaObjectName = $this->lexer->lookahead['value']; + $schemaObjectName = $this->lexer->lookahead->value; $this->lexer->moveNext(); return new Identifier((string)$schemaObjectName); diff --git a/typo3/sysext/core/composer.json b/typo3/sysext/core/composer.json index a384bd7a87470a6ea2b56f58e86883dc408a5324..00dad5132778c382524ae85e8fad4f3711aad418 100644 --- a/typo3/sysext/core/composer.json +++ b/typo3/sysext/core/composer.json @@ -32,11 +32,11 @@ "composer-runtime-api": "^2.1", "bacon/bacon-qr-code": "^2.0.7", "christian-riesen/base32": "^1.6", - "doctrine/annotations": "^1.13.3", + "doctrine/annotations": "^1.13.3 || ^2.0", "doctrine/dbal": "^3.5.1", - "doctrine/event-manager": "^1.1.2", - "doctrine/lexer": "^1.2.3", - "egulias/email-validator": "^3.2.1", + "doctrine/event-manager": "^2.0", + "doctrine/lexer": "^2.0 || ^3.0", + "egulias/email-validator": "^4.0", "enshrined/svg-sanitize": "^0.15.4", "firebase/php-jwt": "^6.3.1", "guzzlehttp/guzzle": "^7.5.0",